diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a8defe1..9b0db8178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Added a YAML linter ([#312](https://github.com/opensearch-project/opensearch-api-specification/pull/312)) - Added linter to validate order of spec operations ([#325](https://github.com/opensearch-project/opensearch-api-specification/pull/326)) ([#326](https://github.com/opensearch-project/opensearch-api-specification/pull/326)) - Added support to read outputs from requests in tests([#324](https://github.com/opensearch-project/opensearch-api-specification/pull/324)) - +- Added `eslint-plugin-eslint-comments` ([#333](https://github.com/opensearch-project/opensearch-api-specification/pull/333)) + ### Changed - Replaced Smithy with a native OpenAPI spec ([#189](https://github.com/opensearch-project/opensearch-api-specification/issues/189)) diff --git a/eslint.config.mjs b/eslint.config.mjs index 1f34d6d2b..37b28e929 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,10 +1,11 @@ -import pluginJs from '@eslint/js' -import pluginTs from '@typescript-eslint/eslint-plugin' +import globals from 'globals' import parserTs from '@typescript-eslint/parser' -import eslintPluginYml from 'eslint-plugin-yml' import parserYml from "yaml-eslint-parser" -import globals from 'globals' -import licenseHeader from 'eslint-plugin-license-header' +import pluginComments from 'eslint-plugin-eslint-comments' +import pluginJs from '@eslint/js' +import pluginLicenseHeader from 'eslint-plugin-license-header' +import pluginTs from '@typescript-eslint/eslint-plugin' +import pluginYml from 'eslint-plugin-yml' export default [ pluginJs.configs.recommended, @@ -22,10 +23,12 @@ export default [ }, plugins: { '@typescript-eslint': pluginTs, - 'license-header': licenseHeader + 'license-header': pluginLicenseHeader, + 'eslint-comments': pluginComments }, rules: { ...pluginJs.configs.recommended.rules, + ...pluginComments.configs.recommended.rules, ...pluginTs.configs["recommended-type-checked"].rules, '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-explicit-any': 'off', @@ -85,17 +88,17 @@ export default [ '* compatible open source license.', '*/' ] - ] + ], } }, - ...eslintPluginYml.configs['flat/standard'], + ...pluginYml.configs['flat/standard'], { files: ["**/*.yaml", "**/*.yml"], languageOptions: { parser: parserYml }, plugins: { - yml: eslintPluginYml + yml: pluginYml }, rules: { 'yml/no-empty-document': 'off', diff --git a/package-lock.json b/package-lock.json index 79bc21062..e4a923b7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@typescript-eslint/eslint-plugin": "^6.21.0", "eslint": "^8.57.0", "eslint-config-standard-with-typescript": "^43.0.1", + "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-license-header": "^0.6.1", "eslint-plugin-n": "^16.6.2", @@ -3199,6 +3200,34 @@ "eslint": ">=8" } }, + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "engines": { + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-eslint-comments/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/eslint-plugin-import": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", diff --git a/package.json b/package.json index 05091ae84..0ca2ad64e 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "coverage:spec": "ts-node tools/src/coverage/coverage.ts", "dump-cluster-spec": "ts-node tools/src/dump-cluster-spec/dump-cluster-spec.ts", "lint:spec": "ts-node tools/src/linter/lint.ts", - "lint": "eslint .", - "lint--fix": "eslint . --fix", + "lint": "eslint . --report-unused-disable-directives", + "lint--fix": "eslint . --fix --report-unused-disable-directives", "merge": "ts-node tools/src/merger/merge.ts", "test": "npm run test:unit && npm run test:integ", "jest": "jest", @@ -38,6 +38,7 @@ "@typescript-eslint/eslint-plugin": "^6.21.0", "eslint": "^8.57.0", "eslint-config-standard-with-typescript": "^43.0.1", + "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-license-header": "^0.6.1", "eslint-plugin-n": "^16.6.2", diff --git a/tools/src/tester/OperationLocator.ts b/tools/src/tester/OperationLocator.ts index df0f2dc91..f5918f2bb 100644 --- a/tools/src/tester/OperationLocator.ts +++ b/tools/src/tester/OperationLocator.ts @@ -30,7 +30,6 @@ export default class OperationLocator { if (operation == null) return undefined this.#deref(operation) const parameters = _.keyBy(operation.parameters ?? [], 'name') - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions this.cached_operations[cache_key] = { ...operation, parameters } as ParsedOperation return this.cached_operations[cache_key] } diff --git a/tools/src/tester/StoryOutputs.ts b/tools/src/tester/StoryOutputs.ts index 37a936dd9..ab06f3733 100644 --- a/tools/src/tester/StoryOutputs.ts +++ b/tools/src/tester/StoryOutputs.ts @@ -7,7 +7,7 @@ * compatible open source license. */ -import { type ChapterOutput } from './ChapterOutput' +import { ChapterOutput } from './ChapterOutput' import { OutputReference } from './types/eval.types' import { type Parameter } from './types/story.types' diff --git a/tools/src/tester/_generate_story_types.ts b/tools/src/tester/_generate_story_types.ts index 6113e7948..d4ab6271e 100644 --- a/tools/src/tester/_generate_story_types.ts +++ b/tools/src/tester/_generate_story_types.ts @@ -24,15 +24,30 @@ void js2ts.compile(schema, 'Story', singleQuote: true, singleAttributePerLine: true }, - // multiline comment - bannerComment: `/* eslint-disable */ - -/** - * This file was automatically generated by json-schema-to-typescript. - * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, - * and run json-schema-to-typescript to regenerate this file by running: - * "npx ts-node tools/src/tester/_generate_story_types.ts" in a terminal. - */` + bannerComment: `/* +* This file was automatically generated by json-schema-to-typescript. +* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, +* and run json-schema-to-typescript to regenerate this file by running: +* "npx ts-node tools/src/tester/_generate_story_types.ts" in a terminal. +*/ +` + }) + .then(ts => { + fs.writeFileSync('tools/src/tester/types/story.types.ts', `/* +* Copyright OpenSearch Contributors +* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +*/ + +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/consistent-indexed-object-style */ +` + + ts + ` +/* eslint-enable @typescript-eslint/ban-types */ +/* eslint-enable @typescript-eslint/consistent-indexed-object-style */ +`) }) - .then(ts => { fs.writeFileSync('tools/src/tester/types/story.types.ts', ts) }) diff --git a/tools/src/tester/types/story.types.ts b/tools/src/tester/types/story.types.ts index c7d52c3d1..38ead0bc3 100644 --- a/tools/src/tester/types/story.types.ts +++ b/tools/src/tester/types/story.types.ts @@ -1,6 +1,16 @@ -/* eslint-disable */ +/* +* Copyright OpenSearch Contributors +* SPDX-License-Identifier: Apache-2.0 +* +* The OpenSearch Contributors require contributions made to +* this file be licensed under the Apache-2.0 license or a +* compatible open source license. +*/ -/** +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/consistent-indexed-object-style */ + +/* * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file by running: @@ -129,3 +139,6 @@ export interface ActualResponse { */ error?: {}; } + +/* eslint-enable @typescript-eslint/ban-types */ +/* eslint-enable @typescript-eslint/consistent-indexed-object-style */ diff --git a/tools/tests/linter/factories/namespace_file.ts b/tools/tests/linter/factories/namespace_file.ts index f38ea0e35..6b661989a 100644 --- a/tools/tests/linter/factories/namespace_file.ts +++ b/tools/tests/linter/factories/namespace_file.ts @@ -31,7 +31,7 @@ export function mocked_namespace_file (ops: { returned_values?: MockedReturnedVa // eslint-disable-next-line @typescript-eslint/dot-notation if (ops.groups_errors) ns_file['_operation_groups'] = ops.groups_errors.map((errors) => mocked_operation_group({ validate: errors })) - // eslint-disable-next-line @typescript-eslint/dot-notation,@typescript-eslint/consistent-type-assertions + // eslint-disable-next-line @typescript-eslint/dot-notation if (ops.spec) ns_file['_spec'] = { paths: {}, components: {}, ...ops.spec } as OpenAPIV3.Document if (ops.returned_values) { diff --git a/tools/tests/linter/factories/operation.ts b/tools/tests/linter/factories/operation.ts index d2ee7f883..07b9dee68 100644 --- a/tools/tests/linter/factories/operation.ts +++ b/tools/tests/linter/factories/operation.ts @@ -27,7 +27,7 @@ interface MockedReturnedValues { } export function mocked_operation (returned_values: MockedReturnedValues): Operation { - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + const op: Operation = new Operation('', '', '', {} as OperationSpec) if (returned_values.validate) { diff --git a/tools/tests/tester/start.test.ts b/tools/tests/tester/start.test.ts index 526669f5b..70e52acae 100644 --- a/tools/tests/tester/start.test.ts +++ b/tools/tests/tester/start.test.ts @@ -115,7 +115,7 @@ function chapter(synopsis: string, request: ChapterRequest): Chapter { } } -/* eslint-disable no-template-curly-in-string */ + test('check_story_variables', () => { const check_story_variables = (s: Story): StoryEvaluation | undefined => StoryEvaluator.check_story_variables(s, 'display_path', 'full_path') const failed = (prologues: ChapterEvaluation[] = [], chapters: ChapterEvaluation[] = []): StoryEvaluation => ({ @@ -193,7 +193,7 @@ test('check_story_variables', () => { ] })).toStrictEqual(undefined) }) -/* eslint-enable no-template-curly-in-string */ + test.todo('--tab-width') diff --git a/tools/tests/tester/story_outputs.test.ts b/tools/tests/tester/story_outputs.test.ts index 4409936b3..2f06f89c4 100644 --- a/tools/tests/tester/story_outputs.test.ts +++ b/tools/tests/tester/story_outputs.test.ts @@ -11,61 +11,55 @@ import { ChapterOutput } from 'tester/ChapterOutput' import { StoryOutputs } from 'tester/StoryOutputs' const story_outputs = new StoryOutputs({ - chapter_id: new ChapterOutput({ - x: 1, - y: 2 - }) + chapter_id: new ChapterOutput({ + x: 1, + y: 2 }) - - /* eslint-disable no-template-curly-in-string */ - test('resolve_string', () => { - expect(story_outputs.resolve_string('${chapter_id.x}')).toEqual(1) - expect(story_outputs.resolve_string('some_str')).toEqual('some_str') - }) - /* eslint-enable no-template-curly-in-string */ - - test('resolve_value', () => { - /* eslint-disable no-template-curly-in-string */ - const value = { - a: '${chapter_id.x}', - b: ['${chapter_id.x}', '${chapter_id.y}', 3], +}) + +test('resolve_string', () => { + expect(story_outputs.resolve_string('${chapter_id.x}')).toEqual(1) + expect(story_outputs.resolve_string('some_str')).toEqual('some_str') +}) + +test('resolve_value', () => { + const value = { + a: '${chapter_id.x}', + b: ['${chapter_id.x}', '${chapter_id.y}', 3], + c: { + d: '${chapter_id.x}', + e: 'str', + f: true + }, + g: 123 + } + expect(story_outputs.resolve_value(value)).toEqual( + { + a: 1, + b: [1, 2, 3], c: { - d: '${chapter_id.x}', + d: 1, e: 'str', f: true }, g: 123 } - /* eslint-enable no-template-curly-in-string */ - expect(story_outputs.resolve_value(value)).toEqual( - { - a: 1, - b: [1, 2, 3], - c: { - d: 1, - e: 'str', - f: true - }, - g: 123 - } - ) - }) - - test('resolve_params', () => { - /* eslint-disable no-template-curly-in-string */ - const parameters = { - a: '${chapter_id.x}', - b: '${chapter_id.y}', - c: 3, - d: 'str' - } - /* eslint-enable no-template-curly-in-string */ + ) +}) + +test('resolve_params', () => { + const parameters = { + a: '${chapter_id.x}', + b: '${chapter_id.y}', + c: 3, + d: 'str' + } expect(story_outputs.resolve_params(parameters)).toEqual({ - a: 1, - b: 2, - c: 3, - d: 'str' - }) + a: 1, + b: 2, + c: 3, + d: 'str' }) - - +}) + +