-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
spread-flags
/only-extend-SfCommand
/`no-default-and-depe…
…nds-on-flags` rules (#440) * feat: add no default and depends on flag configuration rule * chore: edge case * chore: fix circular error * docs: generate docs * chore: fix [0] * chore: fix [0] (2) * Wr/spread base flags (#441) * feat: add only extend from SfCommand * feat: add spread super command flags prop * chore: update messages to include super class name * chore: identify SfCommand parent class * chore: move from error to warn on rollout * chore: ..flags, ...baseFlags * chore: update comment
- Loading branch information
1 parent
07ee26b
commit d4e7391
Showing
14 changed files
with
521 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Do not allow creation of a flag with default value and dependsOn (`sf-plugin/no-default-and-depends-on-flags`) | ||
|
||
💼 This rule is enabled in the following configs: ✈️ `migration`, ✅ `recommended`. | ||
|
||
<!-- end auto-generated rule header --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* 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 { AST_NODE_TYPES } from '@typescript-eslint/utils'; | ||
import { RuleCreator } from '@typescript-eslint/utils/eslint-utils'; | ||
import { ancestorsContainsSfCommand, isInCommandDirectory } from '../shared/commands'; | ||
import { flagPropertyIsNamed, isFlag } from '../shared/flags'; | ||
|
||
export const noDefaultDependsOnFlags = RuleCreator.withoutDocs({ | ||
meta: { | ||
docs: { | ||
description: 'Do not allow creation of a flag with default value and dependsOn', | ||
recommended: 'recommended', | ||
}, | ||
messages: { | ||
message: 'Cannot create a flag with a default value and dependsOn', | ||
}, | ||
type: 'problem', | ||
schema: [], | ||
}, | ||
defaultOptions: [], | ||
create(context) { | ||
return isInCommandDirectory(context) | ||
? { | ||
Property(node): void { | ||
// is a flag | ||
if ( | ||
isFlag(node) && | ||
ancestorsContainsSfCommand(context.getAncestors()) && | ||
node.value?.type === AST_NODE_TYPES.CallExpression && | ||
node.value.arguments?.[0]?.type === AST_NODE_TYPES.ObjectExpression | ||
) { | ||
const dependsOnProperty = node.value.arguments[0].properties.find( | ||
(property) => property.type === AST_NODE_TYPES.Property && flagPropertyIsNamed(property, 'dependsOn') | ||
); | ||
const defaultValueProperty = node.value.arguments[0].properties.find( | ||
(property) => property.type === AST_NODE_TYPES.Property && flagPropertyIsNamed(property, 'default') | ||
); | ||
|
||
// @ts-expect-error from the node (flag), go up a level (parent) and find the dependsOn flag definition, see if it has a default | ||
const dependsOnFlagDefaultValue = node.parent.properties | ||
.find( | ||
(f) => | ||
// @ts-expect-error value type on dependsOn | ||
f.type === AST_NODE_TYPES.Property && f.key.name === dependsOnProperty?.value.elements?.at(0)?.value | ||
) | ||
?.value.arguments?.at(0) | ||
?.properties.find((p) => p.key.name === 'default'); | ||
if (dependsOnProperty && defaultValueProperty && !dependsOnFlagDefaultValue) { | ||
context.report({ | ||
node: dependsOnProperty, | ||
messageId: 'message', | ||
}); | ||
} | ||
} | ||
}, | ||
} | ||
: {}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* 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 { | ||
isInCommandDirectory, | ||
extendsSfCommand, | ||
} from "../shared/commands"; | ||
import { RuleCreator } from '@typescript-eslint/utils/eslint-utils'; | ||
|
||
export const onlyExtendSfCommand = RuleCreator.withoutDocs({ | ||
meta: { | ||
docs: { | ||
description: 'Only allow commands that directly extend SfCommand', | ||
recommended: 'recommended', | ||
}, | ||
messages: { | ||
message: 'In order to inherit default flags correctly, extend from SfCommand directly', | ||
}, | ||
type: 'problem', | ||
schema: [], | ||
}, | ||
defaultOptions: [], | ||
create(context) { | ||
return isInCommandDirectory(context) | ||
? { | ||
ClassDeclaration(node): void { | ||
// verify it extends SfCommand | ||
if (!extendsSfCommand(node) && node.id) { | ||
context.report({ | ||
node: node.id, | ||
messageId: 'message', | ||
}); | ||
} | ||
}, | ||
} | ||
: {}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* 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 { isInCommandDirectory, ancestorsContainsSfCommand, getSfCommand } from '../shared/commands'; | ||
import { RuleCreator } from '@typescript-eslint/utils/eslint-utils'; | ||
import { | ||
getBaseFlagsStaticPropertyFromCommandClass, | ||
getFlagsStaticPropertyFromCommandClass, | ||
isFlagsStaticProperty, | ||
} from '../shared/flags'; | ||
import { ASTUtils, AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; | ||
|
||
export const spreadBaseFlags = RuleCreator.withoutDocs({ | ||
meta: { | ||
docs: { | ||
description: | ||
"When not directly extending SfCommand, the parent's flags must be spread like flags = { ...{{parent}}.{{property}} }", | ||
recommended: 'recommended', | ||
}, | ||
messages: { | ||
message: | ||
"When not directly extending SfCommand, the parent's flags must be spread like flags = { ...{{parent}}.{{property}} }", | ||
}, | ||
type: 'problem', | ||
schema: [], | ||
}, | ||
defaultOptions: [], | ||
create(context) { | ||
return isInCommandDirectory(context) | ||
? { | ||
ClassDeclaration(node): void { | ||
const flagsProperty = getFlagsStaticPropertyFromCommandClass(node); | ||
if (flagsProperty) { | ||
// @ts-ignore SpreadElement (...) on property==='flags' (BaseCommand.flags) | ||
const flags = flagsProperty?.value?.properties?.find( | ||
(f) => f.type === 'SpreadElement' && f.argument.property?.name === 'flags' | ||
); | ||
// @ts-ignore name will not be undefined because we're in a command class, which has to at least extend Command | ||
const parent = node.superClass?.name; | ||
|
||
if (parent !== 'SfCommand' && !flags) { | ||
context.report({ | ||
loc: flagsProperty.loc, | ||
messageId: 'message', | ||
data: { parent, property: 'flags' }, | ||
}); | ||
} | ||
} | ||
|
||
const baseFlagsProperty = getBaseFlagsStaticPropertyFromCommandClass(node); | ||
if (baseFlagsProperty) { | ||
// @ts-ignore SpreadElement (...) on property==='baseFlags' (BaseCommand.baseFlags) | ||
const baseFlags = baseFlagsProperty.value?.properties?.find( | ||
(f) => f.type === 'SpreadElement' && f.argument.property?.name === 'baseFlags' | ||
); | ||
// @ts-ignore name will not be undefined because we're in a command class, which has to at least extend Command | ||
const parent = node.superClass?.name; | ||
|
||
if (parent !== 'SfCommand' && !baseFlags) { | ||
context.report({ | ||
loc: baseFlagsProperty.loc, | ||
messageId: 'message', | ||
data: { parent, property: 'baseFlags' }, | ||
}); | ||
} | ||
} | ||
}, | ||
} | ||
: {}; | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.