Skip to content

Commit

Permalink
feat: extract message on command summary/description
Browse files Browse the repository at this point in the history
  • Loading branch information
mshanemc committed Jun 13, 2022
1 parent 5e5318f commit 6ffdebe
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 6 deletions.
9 changes: 6 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import { noDuplicateShortCharacters } from './rules/noDuplicateShortCharacters';
import { flagSummary } from './rules/flagSummary';
import { flagCasing } from './rules/flagCasing';
import { extractMessage } from './rules/extractMessage';
import { extractMessageFlags } from './rules/extractMessageFlags';
import { flagCrossReferences } from './rules/flagCrossReferences';
import { commandSummary } from './rules/commandSummary';
import { commandExamples } from './rules/commandExamples';
import { extractMessageCommand } from './rules/extractMessageCommand';

export = {
configs: {
Expand All @@ -22,7 +23,8 @@ export = {
'sf-plugin/no-duplicate-short-characters': 'error',
'sf-plugin/flag-case': 'error',
'sf-plugin/flag-summary': 'error',
'sf-plugin/no-hardcoded-messages': 'warn',
'sf-plugin/no-hardcoded-messages-flags': 'warn',
'sf-plugin/no-hardcoded-messages-commands': 'warn',
'sf-plugin/flag-cross-references': 'error',
},
},
Expand All @@ -31,7 +33,8 @@ export = {
'no-duplicate-short-characters': noDuplicateShortCharacters,
'flag-case': flagCasing,
'flag-summary': flagSummary,
'no-hardcoded-messages': extractMessage,
'no-hardcoded-messages-flags': extractMessageFlags,
'no-hardcoded-messages-commands': extractMessageCommand,
'flag-cross-references': flagCrossReferences,
'command-summary': commandSummary,
'command-example': commandExamples,
Expand Down
45 changes: 45 additions & 0 deletions src/rules/extractMessageCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { ESLintUtils } from '@typescript-eslint/utils';
import { extendsSfCommand, getClassPropertyIdentifierName, isInCommandDirectory } from '../shared/commands';

const propertiesYouShouldntHardCode = ['description', 'summary'];

export const extractMessageCommand = ESLintUtils.RuleCreator.withoutDocs({
meta: {
docs: {
description: 'Use loaded messages and separate files for messages',
recommended: 'warn',
},
messages: {
message:
'Summary/Description property should use messages.getMessage instead of hardcoding the message. See https://github.com/forcedotcom/sfdx-core/blob/v3/MIGRATING_V2-V3.md#messages',
},
type: 'problem',
schema: [],
},
defaultOptions: [],
create(context) {
return {
ClassDeclaration(node): void {
// verify it extends SfCommand
if (isInCommandDirectory(context) && extendsSfCommand(node)) {
node.body.body
.filter((prop) => propertiesYouShouldntHardCode.includes(getClassPropertyIdentifierName(prop)))
.forEach((prop) => {
if (prop.type === 'PropertyDefinition' && prop.value.type === 'Literal') {
context.report({
node,
messageId: 'message',
});
}
});
}
},
};
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
import { isFlag } from '../shared/flags';
import { ancestorsContainsSfCommand, isInCommandDirectory } from '../shared/commands';

export const extractMessage = ESLintUtils.RuleCreator.withoutDocs({
export const extractMessageFlags = ESLintUtils.RuleCreator.withoutDocs({
meta: {
docs: {
description: 'Use loaded messages and separate files for messages',
Expand Down
4 changes: 2 additions & 2 deletions test/rules/extractMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { ESLintUtils } from '@typescript-eslint/utils';
import { extractMessage } from '../../src/rules/extractMessage';
import { extractMessageFlags } from '../../src/rules/extractMessageFlags';

const ruleTester = new ESLintUtils.RuleTester({
parser: '@typescript-eslint/parser',
});

ruleTester.run('no duplicate short characters', extractMessage, {
ruleTester.run('no duplicate short characters', extractMessageFlags, {
valid: [
// no messages is fine
{
Expand Down
99 changes: 99 additions & 0 deletions test/rules/extractMessageCommand.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { ESLintUtils } from '@typescript-eslint/utils';
import { extractMessageCommand } from '../../src/rules/extractMessageCommand';

const ruleTester = new ESLintUtils.RuleTester({
parser: '@typescript-eslint/parser',
});

ruleTester.run('no hardcoded summary/description on command', extractMessageCommand, {
valid: [
{
filename: 'src/commands/foo.ts',
code: `
export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
public static readonly description = messages.getMessage('description');
public static readonly summary = messages.getMessage('summary');
}
`,
},
// description only
{
filename: 'src/commands/foo.ts',
code: `
export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
public static readonly description = messages.getMessage('description');
}
`,
},
// summary only
{
filename: 'src/commands/foo.ts',
code: `
export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
public static readonly summary = messages.getMessage('summary');
}
`,
},
// not an sf command
{
filename: 'src/foo.ts',
code: `
export default class EnvCreateScratch extends SomethingElse<ScratchCreateResponse> {
public static readonly description = 'foo';
public static readonly summary = 'bar';
}
`,
},
// all sorts of violations but not in the commands directory
{
filename: 'src/foo.ts',
code: `
export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
public static readonly description = 'foo';
public static readonly summary = 'bar';
}
`,
},
],
invalid: [
{
filename: 'src/commands/foo.ts',

errors: [
{
messageId: 'message',
},
],
code: `
export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
public static readonly description = 'foo';
public static readonly summary = messages.getMessage('summary');
}
`,
},
{
errors: [
{
messageId: 'message',
},
{
messageId: 'message',
},
],
filename: 'src/commands/foo.ts',

code: `
export default class EnvCreateScratch extends SfCommand<ScratchCreateResponse> {
public static readonly description = 'foo';
public static readonly summary = 'bar';
}
`,
},
],
});

0 comments on commit 6ffdebe

Please sign in to comment.