<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Lazy } from 'vs/base/common/lazy';
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IPosition } from 'vs/editor/common/core/position';
import { CodeActionTriggerType } from 'vs/editor/common/modes';
import { CodeActionItem, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction';
import { MessageController } from 'vs/editor/contrib/message/messageController';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CodeActionMenu, CodeActionShowOptions } from './codeActionMenu';
import { CodeActionsState } from './codeActionModel';
import { LightBulbWidget } from './lightBulbWidget';
import { CodeActionAutoApply, CodeActionTrigger } from './types';

export class CodeActionUi extends Disposable {

	private readonly _codeActionWidget: Lazy<CodeActionMenu>;
	private readonly _lightBulbWidget: Lazy<LightBulbWidget>;
	private readonly _activeCodeActions = this._register(new MutableDisposable<CodeActionSet>());

	constructor(
		private readonly _editor: ICodeEditor,
		quickFixActionId: string,
		preferredFixActionId: string,
		private readonly delegate: {
			applyCodeAction: (action: CodeActionItem, regtriggerAfterApply: boolean) => Promise<void>
		},
		@IInstantiationService instantiationService: IInstantiationService,
	) {
		super();

		this._codeActionWidget = new Lazy(() => {
			return this._register(instantiationService.createInstance(CodeActionMenu, this._editor, {
				onSelectCodeAction: async (action) => {
					this.delegate.applyCodeAction(action, /* retrigger */ true);
				}
			}));
		});

		this._lightBulbWidget = new Lazy(() => {
			const widget = this._register(instantiationService.createInstance(LightBulbWidget, this._editor, quickFixActionId, preferredFixActionId));
			this._register(widget.onClick(e => this.showCodeActionList(e.trigger, e.actions, e, { includeDisabledActions: false })));
			return widget;
		});
	}

	public async update(newState: CodeActionsState.State): Promise<void> {
		if (newState.type !== CodeActionsState.Type.Triggered) {
			this._lightBulbWidget.rawValue?.hide();
			return;
		}

		let actions: CodeActionSet;
		try {
			actions = await newState.actions;
		} catch (e) {
			onUnexpectedError(e);
			return;
		}

		this._lightBulbWidget.getValue().update(actions, newState.trigger, newState.position);

		if (newState.trigger.type === CodeActionTriggerType.Manual) {
			if (newState.trigger.filter?.include) { // Triggered for specific scope
				// Check to see if we want to auto apply.

				const validActionToApply = this.tryGetValidActionToApply(newState.trigger, actions);
				if (validActionToApply) {
					try {
						await this.delegate.applyCodeAction(validActionToApply, false);
					} finally {
						actions.dispose();
					}<commit_msg>Check to see if widget has been disposed of while actions are resolving<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Lazy } from 'vs/base/common/lazy';
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IPosition } from 'vs/editor/common/core/position';
import { CodeActionTriggerType } from 'vs/editor/common/modes';
import { CodeActionItem, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction';
import { MessageController } from 'vs/editor/contrib/message/messageController';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CodeActionMenu, CodeActionShowOptions } from './codeActionMenu';
import { CodeActionsState } from './codeActionModel';
import { LightBulbWidget } from './lightBulbWidget';
import { CodeActionAutoApply, CodeActionTrigger } from './types';

export class CodeActionUi extends Disposable {

	private readonly _codeActionWidget: Lazy<CodeActionMenu>;
	private readonly _lightBulbWidget: Lazy<LightBulbWidget>;
	private readonly _activeCodeActions = this._register(new MutableDisposable<CodeActionSet>());

	#disposed = false;

	constructor(
		private readonly _editor: ICodeEditor,
		quickFixActionId: string,
		preferredFixActionId: string,
		private readonly delegate: {
			applyCodeAction: (action: CodeActionItem, regtriggerAfterApply: boolean) => Promise<void>
		},
		@IInstantiationService instantiationService: IInstantiationService,
	) {
		super();

		this._codeActionWidget = new Lazy(() => {
			return this._register(instantiationService.createInstance(CodeActionMenu, this._editor, {
				onSelectCodeAction: async (action) => {
					this.delegate.applyCodeAction(action, /* retrigger */ true);
				}
			}));
		});

		this._lightBulbWidget = new Lazy(() => {
			const widget = this._register(instantiationService.createInstance(LightBulbWidget, this._editor, quickFixActionId, preferredFixActionId));
			this._register(widget.onClick(e => this.showCodeActionList(e.trigger, e.actions, e, { includeDisabledActions: false })));
			return widget;
		});
	}

	dispose() {
		this.#disposed = true;
		super.dispose();
	}

	public async update(newState: CodeActionsState.State): Promise<void> {
		if (newState.type !== CodeActionsState.Type.Triggered) {
			this._lightBulbWidget.rawValue?.hide();
			return;
		}

		let actions: CodeActionSet;
		try {
			actions = await newState.actions;
		} catch (e) {
			onUnexpectedError(e);
			return;
		}

		if (this.#disposed) {
			return;
		}

		this._lightBulbWidget.getValue().update(actions, newState.trigger, newState.position);

		if (newState.trigger.type === CodeActionTriggerType.Manual) {
			if (newState.trigger.filter?.include) { // Triggered for specific scope
				// Check to see if we want to auto apply.

				const validActionToApply = this.tryGetValidActionToApply(newState.trigger, actions);
				if (validActionToApply) {
					try {
						await this.delegate.applyCodeAction(validActionToApply, false);
					} finally {
						actions.dispose();
					}
{'fraction_non_alphanumeric': 0.16237337192474674, 'fraction_numerical': 0.0, 'mean_word_length': 3.682249322493225, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6953506', 'n_tokens_mistral': 2096, 'n_tokens_neox': 1887, 'n_words': 431}