Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions messages/run-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@ To output the results to multiple files, specify this flag multiple times. For e

If you specify a file within a folder, such as `--output-file ./out/results.json`, the folder must already exist, or you get an error. If the file already exists, it's overwritten without prompting.

# flags.include-fixes.summary

Include fix data for violations when available.

# flags.include-fixes.description

When enabled, the output includes fix information for violations that have auto-fixes available. Each fix contains a code location and the replacement code. This flag may increase analysis time because engines must perform additional processing to compute fixes.

# flags.include-suggestions.summary

Include suggestion data for violations when available.

# flags.include-suggestions.description

When enabled, the output includes suggestion information for violations that have suggestions available. Each suggestion contains a code location and a message describing the suggested change.

# error.invalid-severity-threshold

Expected --severity-threshold=%s to be one of: %s
Expand Down
17 changes: 15 additions & 2 deletions src/commands/code-analyzer/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,18 @@ export default class RunCommand extends SfCommand<void> implements Displayable {
description: getMessage(BundleName.RunCommand, 'flags.config-file.description'),
char: 'c',
exists: true
})
}),
// === Flags pertaining to fixes and suggestions ===
'include-fixes': Flags.boolean({
summary: getMessage(BundleName.RunCommand, 'flags.include-fixes.summary'),
description: getMessage(BundleName.RunCommand, 'flags.include-fixes.description'),
default: false
}),
'include-suggestions': Flags.boolean({
summary: getMessage(BundleName.RunCommand, 'flags.include-suggestions.summary'),
description: getMessage(BundleName.RunCommand, 'flags.include-suggestions.description'),
default: false
}),
};

public async run(): Promise<void> {
Expand All @@ -84,7 +95,9 @@ export default class RunCommand extends SfCommand<void> implements Displayable {
'workspace': parsedFlags['workspace'],
'severity-threshold': parsedFlags['severity-threshold'] === undefined ? undefined :
convertThresholdToEnum(parsedFlags['severity-threshold'].toLowerCase()),
'target': parsedFlags['target']
'target': parsedFlags['target'],
'include-fixes': parsedFlags['include-fixes'],
'include-suggestions': parsedFlags['include-suggestions']
};
await action.execute(runInput);
}
Expand Down
9 changes: 7 additions & 2 deletions src/lib/actions/RunAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
'severity-threshold'?: SeverityLevel;
target?: string[];
workspace: string[];

'include-fixes'?: boolean;
'include-suggestions'?: boolean;
}

export class RunAction {
Expand Down Expand Up @@ -75,7 +76,11 @@
// that's when progress events can start being emitted.
this.dependencies.progressListeners.forEach(listener => listener.listen(core));
const ruleSelection: RuleSelection = await core.selectRules(input['rule-selector'], {workspace});
const runOptions: RunOptions = {workspace};
const runOptions: RunOptions = {
workspace,
includeFixes: input['include-fixes'],

Check failure on line 81 in src/lib/actions/RunAction.ts

View workflow job for this annotation

GitHub Actions / run_tests / unit-tests (lts/*, lts, ubuntu-latest)

Object literal may only specify known properties, and 'includeFixes' does not exist in type 'RunOptions'.

Check failure on line 81 in src/lib/actions/RunAction.ts

View workflow job for this annotation

GitHub Actions / run_tests / build-installable-tarball

Object literal may only specify known properties, and 'includeFixes' does not exist in type 'RunOptions'.

Check failure on line 81 in src/lib/actions/RunAction.ts

View workflow job for this annotation

GitHub Actions / run_tests / unit-tests (lts/*, lts, windows-latest)

Object literal may only specify known properties, and 'includeFixes' does not exist in type 'RunOptions'.

Check failure on line 81 in src/lib/actions/RunAction.ts

View workflow job for this annotation

GitHub Actions / run_tests / unit-tests (lts/*, lts, macos-latest)

Object literal may only specify known properties, and 'includeFixes' does not exist in type 'RunOptions'.
includeSuggestions: input['include-suggestions']
};
const results: RunResults = await core.run(ruleSelection, runOptions);
this.emitEngineTelemetry(ruleSelection, results, enginePlugins.flatMap(p => p.getAvailableEngineNames()));
// After Core is done running, the listeners need to be told to stop, since some of them have persistent UI elements
Expand Down
71 changes: 71 additions & 0 deletions test/lib/actions/RunAction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,77 @@ describe('RunAction tests', () => {
expect(spyTelemetryEmitter.getCapturedTelemetry()[3].data.violationCount).toEqual(0);
});
})

describe('include-fixes and include-suggestions flags', () => {
it.each([
{case: 'neither flag set', includeFixes: undefined, includeSuggestions: undefined},
{case: 'include-fixes=false, include-suggestions=false', includeFixes: false, includeSuggestions: false},
])('When $case, both are passed as-is to RunOptions', async ({includeFixes, includeSuggestions}) => {
const input: RunInput = {
'rule-selector': ['all'],
'workspace': ['.'],
'output-file': [],
'include-fixes': includeFixes,
'include-suggestions': includeSuggestions
};


await action.execute(input);
const runOptions = engine1.runRulesCallHistory[0].runOptions;
expect(runOptions.includeFixes).toEqual(includeFixes);
expect(runOptions.includeSuggestions).toEqual(includeSuggestions);
});

it('When include-fixes=true, it is forwarded to RunOptions', async () => {

const input: RunInput = {
'rule-selector': ['all'],
'workspace': ['.'],
'output-file': [],
'include-fixes': true,
'include-suggestions': false
};

await action.execute(input);

const runOptions = engine1.runRulesCallHistory[0].runOptions;
expect(runOptions.includeFixes).toBe(true);
expect(runOptions.includeSuggestions).toBe(false);
});

it('When include-suggestions=true, it is forwarded to RunOptions', async () => {

const input: RunInput = {
'rule-selector': ['all'],
'workspace': ['.'],
'output-file': [],
'include-fixes': false,
'include-suggestions': true
};

await action.execute(input);

const runOptions = engine1.runRulesCallHistory[0].runOptions;
expect(runOptions.includeFixes).toBe(false);
expect(runOptions.includeSuggestions).toBe(true);
});

it('When both include-fixes=true and include-suggestions=true, both are forwarded to RunOptions', async () => {
const input: RunInput = {
'rule-selector': ['all'],
'workspace': ['.'],
'output-file': [],
'include-fixes': true,
'include-suggestions': true
};

await action.execute(input);

const runOptions = engine1.runRulesCallHistory[0].runOptions;
expect(runOptions.includeFixes).toBe(true);
expect(runOptions.includeSuggestions).toBe(true);
});
});
});

// TODO: Whenever we decide to document the custom_engine_plugin_modules flag in our configuration file, then we'll want
Expand Down
Loading