Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow codeActionsOnSave to trigger for autoSave #190516

Merged
merged 26 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6e59df2
removed saveReason check for autosave
justschen Aug 15, 2023
8af05c5
Merge branch 'main' into justin/codeActions-autoSave
justschen Aug 16, 2023
70f859c
Merge branch 'microsoft:main' into justin/codeActions-autoSave
justschen Aug 21, 2023
7087d2b
Merge branch 'main' into justin/codeActions-autoSave
justschen Aug 21, 2023
901429b
modified setting values and enabling on autosave or not
justschen Aug 21, 2023
301f9dd
cleanup
justschen Aug 21, 2023
3f7b685
Merge branch 'main' into justin/codeActions-autoSave
justschen Aug 21, 2023
7e45d09
add default to false settings
justschen Aug 21, 2023
d8ee559
Merge branch 'main' into justin/codeActions-autoSave
justschen Aug 22, 2023
f86e16e
modified code action save settings
justschen Aug 22, 2023
de0fe63
changed default setting
justschen Aug 22, 2023
29de6ce
Merge branch 'main' into justin/codeActions-autoSave
justschen Aug 22, 2023
46de666
cleanup code and added backward compatibility
justschen Aug 23, 2023
6be4532
aded minor comment and checking commit signing
justschen Aug 24, 2023
1d0cf83
second check on commit signing (sorry)
justschen Aug 24, 2023
edcc315
Merge branch 'main' into justin/codeActions-autoSave
justschen Aug 24, 2023
cefc88a
fix typo
justschen Aug 24, 2023
687ad2f
small bugfix and adding proper backward compatibility
justschen Aug 28, 2023
0e6d06c
Merge branch 'main' into justin/codeActions-autoSave
justschen Sep 7, 2023
0159ae8
Merge branch 'microsoft:main' into justin/codeActions-autoSave
justschen Sep 7, 2023
0fdc456
Merge branch 'main' into justin/codeActions-autoSave
justschen Sep 7, 2023
995c5e1
Merge branch 'main' into justin/codeActions-autoSave
justschen Sep 7, 2023
2b5f998
deprecate boolean values by converting them
justschen Sep 13, 2023
7c0770b
Merge branch 'microsoft:main' into justin/codeActions-autoSave
justschen Sep 13, 2023
2cbe61c
Merge branch 'main' into justin/codeActions-autoSave
justschen Sep 14, 2023
d9f3715
Merge branch 'main' into justin/codeActions-autoSave
justschen Sep 14, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { CodeActionsExtensionPoint, ContributedCodeAction } from 'vs/workbench/contrib/codeActions/common/codeActionsExtensionPoint';
import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';

const createCodeActionsAutoSave = (description: string): IJSONSchema => {
return {
type: 'string',
enum: ['always', 'never', 'explicit'],
enumDescriptions: [nls.localize('alwaysSave', 'Always triggers Code Actions on save'), nls.localize('neverSave', 'Never triggers Code Actions on save'), nls.localize('explicitSave', 'Triggers Code Actions only when explicitly saved')],
default: 'explicit',
description: description
};
};

const codeActionsOnSaveDefaultProperties = Object.freeze<IJSONSchemaMap>({
'source.fixAll': {
type: 'boolean',
description: nls.localize('codeActionsOnSave.fixAll', "Controls whether auto fix action should be run on file save.")
}
'source.fixAll': createCodeActionsAutoSave(nls.localize('codeActionsOnSave.fixAll', "Controls whether auto fix action should be run on file save.")),
});

const codeActionsOnSaveSchema: IConfigurationPropertySchema = {
Expand All @@ -30,16 +37,20 @@ const codeActionsOnSaveSchema: IConfigurationPropertySchema = {
type: 'object',
properties: codeActionsOnSaveDefaultProperties,
additionalProperties: {
type: 'boolean'
type: 'string'
},
},
{
type: 'array',
items: { type: 'string' }
}
],
markdownDescription: nls.localize('editor.codeActionsOnSave', 'Run CodeActions for the editor on save. CodeActions must be specified and the editor must not be shutting down. Example: `"source.organizeImports": "explicit" `'),
type: 'object',
additionalProperties: {
type: 'string'
},
default: {},
description: nls.localize('codeActionsOnSave', "Code Action kinds to be run on save."),
scope: ConfigurationScope.LANGUAGE_OVERRIDABLE,
};

Expand Down Expand Up @@ -77,10 +88,7 @@ export class CodeActionsContribution extends Disposable implements IWorkbenchCon
private updateConfigurationSchema(codeActionContributions: readonly CodeActionsExtensionPoint[]) {
const newProperties: IJSONSchemaMap = { ...codeActionsOnSaveDefaultProperties };
for (const [sourceAction, props] of this.getSourceActions(codeActionContributions)) {
newProperties[sourceAction] = {
type: 'boolean',
description: nls.localize('codeActionsOnSave.generic', "Controls whether '{0}' actions should be run on file save.", props.title)
};
newProperties[sourceAction] = createCodeActionsAutoSave(nls.localize('codeActionsOnSave.generic', "Controls whether '{0}' actions should be run on file save.", props.title));
}
codeActionsOnSaveSchema.properties = newProperties;
Registry.as<IConfigurationRegistry>(Extensions.Configuration)
Expand Down
59 changes: 30 additions & 29 deletions src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { CancellationToken } from 'vs/base/common/cancellation';
import { Disposable } from 'vs/base/common/lifecycle';
import * as strings from 'vs/base/common/strings';
import { IActiveCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
Expand All @@ -12,25 +13,24 @@ import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { CodeActionProvider, CodeActionTriggerType } from 'vs/editor/common/languages';
import { ITextModel } from 'vs/editor/common/model';
import { CodeActionTriggerType, CodeActionProvider } from 'vs/editor/common/languages';
import { applyCodeAction, ApplyCodeActionReason, getCodeActions } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { ApplyCodeActionReason, applyCodeAction, getCodeActions } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { CodeActionKind, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/common/types';
import { formatDocumentRangesWithSelectedProvider, formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/browser/format';
import { FormattingMode, formatDocumentRangesWithSelectedProvider, formatDocumentWithSelectedProvider } from 'vs/editor/contrib/format/browser/format';
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgressStep, IProgress, Progress } from 'vs/platform/progress/common/progress';
import { ITextFileService, ITextFileSaveParticipant, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { SaveReason } from 'vs/workbench/common/editor';
import { Disposable } from 'vs/base/common/lifecycle';
import { IWorkbenchContribution, Extensions as WorkbenchContributionsExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IProgress, IProgressStep, Progress } from 'vs/platform/progress/common/progress';
import { Registry } from 'vs/platform/registry/common/platform';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchContributionsExtensions } from 'vs/workbench/common/contributions';
import { SaveReason } from 'vs/workbench/common/editor';
import { getModifiedRanges } from 'vs/workbench/contrib/format/browser/formatModified';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { ITextFileEditorModel, ITextFileSaveParticipant, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';

export class TrimWhitespaceParticipant implements ITextFileSaveParticipant {

Expand Down Expand Up @@ -277,24 +277,24 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant {
return;
}

// Do not run code actions on auto save
if (env.reason !== SaveReason.EXPLICIT) {
return undefined;
}

const textEditorModel = model.textEditorModel;
const settingsOverrides = { overrideIdentifier: textEditorModel.getLanguageId(), resource: textEditorModel.uri };

const settingsOverrides = { overrideIdentifier: textEditorModel.getLanguageId(), resource: model.resource };
const setting = this.configurationService.getValue<{ [kind: string]: boolean } | string[]>('editor.codeActionsOnSave', settingsOverrides);
// Convert boolean values to strings
const setting = this.configurationService.getValue<{ [kind: string]: string | boolean }>('editor.codeActionsOnSave', settingsOverrides);
if (!setting) {
return undefined;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of handling the boolean values below, can you add logic here that converts the old boolean settings to the new enum values: false -> "never", true -> "explict". That should simplify the logic

const convertedSetting: { [kind: string]: string } = {};
for (const key in setting) {
if (typeof setting[key] === 'boolean') {
convertedSetting[key] = setting[key] ? 'explicit' : 'never';
} else if (typeof setting[key] === 'string') {
convertedSetting[key] = setting[key] as string;
}
}

const settingItems: string[] = Array.isArray(setting)
? setting
: Object.keys(setting).filter(x => setting[x]);

const codeActionsOnSave = this.createCodeActionsOnSave(settingItems);
const codeActionsOnSave = this.createCodeActionsOnSave(Object.keys(convertedSetting));

if (!Array.isArray(setting)) {
codeActionsOnSave.sort((a, b) => {
Expand All @@ -315,14 +315,15 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant {
return undefined;
}

const excludedActions = Array.isArray(setting)
? []
: Object.keys(setting)
.filter(x => setting[x] === false)
.map(x => new CodeActionKind(x));
const excludedActions = Object.keys(setting)
.filter(x => convertedSetting[x] === 'never' || false)
.map(x => new CodeActionKind(x));

progress.report({ message: localize('codeaction', "Quick Fixes") });
await this.applyOnSaveActions(textEditorModel, codeActionsOnSave, excludedActions, progress, token);

const filteredSaveList = codeActionsOnSave.filter(x => convertedSetting[x.value] === 'always' || (convertedSetting[x.value] === 'explicit') && env.reason === SaveReason.EXPLICIT);

await this.applyOnSaveActions(textEditorModel, filteredSaveList, excludedActions, progress, token);
}

private createCodeActionsOnSave(settingItems: readonly string[]): CodeActionKind[] {
Expand Down