Work on FAR/Rename w/UI reliablity with cancellation (#4314)

This commit is contained in:
Colen Garoutte-Carson 2019-09-24 11:03:49 -07:00 коммит произвёл GitHub
Родитель 46c9e53676
Коммит 6a0d08e09a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 200 добавлений и 143 удалений

Просмотреть файл

@ -1 +1,6 @@
<svg width="137" height="111" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="hidden"><defs><clipPath id="clip0"><path d="M752 541 889 541 889 652 752 652Z" fill-rule="evenodd" clip-rule="evenodd"/></clipPath></defs><g clip-path="url(#clip0)" transform="translate(-752 -541)"><rect x="848" y="549" width="10" height="96"/><path d="M836 545 869.6 545" stroke="#000000" stroke-width="8" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M836 647 869.6 647" stroke="#000000" stroke-width="8" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M0 0 84.1715 0.000104987" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd" transform="matrix(-1 -8.74228e-08 -8.74228e-08 1 840.672 568.5)"/><path d="M0 0 84.1715 0.000104987" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd" transform="matrix(-1 -8.74228e-08 -8.74228e-08 1 840.672 626.5)"/><path d="M0 0 24.96 0.000104987" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd" transform="matrix(-1 -8.74228e-08 -8.74228e-08 1 889.46 568.5)"/><path d="M0 0 24.96 0.000104987" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd" transform="matrix(-1 -8.74228e-08 -8.74228e-08 1 889.46 626.5)"/><path d="M760.5 568.5 760.5 623.266" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M885.5 568.5 885.5 625.486" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M830.5 590.5 830.5 609.7" stroke="#000000" stroke-width="5" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M820.5 600.5 839.7 600.5" stroke="#000000" stroke-width="5" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M806.5 590.5 806.5 609.7" stroke="#000000" stroke-width="5" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M797.5 600.5 816.7 600.5" stroke="#000000" stroke-width="5" stroke-miterlimit="8" fill="none" fill-rule="evenodd"/><path d="M16.5 0C25.6127-2.10067e-15 33 6.71573 33 15 33 23.2843 25.6127 30 16.5 30 15.9798 30 15.4599 29.9776 14.9421 29.933" stroke="#000000" stroke-width="7" stroke-miterlimit="8" fill="none" fill-rule="evenodd" transform="matrix(-1 -8.74228e-08 -8.74228e-08 1 808.5 582.5)"/></g></svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 12.23V3.77L13.13 3H14V2H13L12.69 2.09L11.5 2.9L10.28 2.08L10 2H9V3H9.85L11 3.77V12.23L9.87 13H9V14H10L10.31 13.91L11.5 13.1L12.72 13.92L13 14H14V13H13.15L12 12.23Z" fill="#C5C5C5"/>
<path d="M1 10.5V5.5L1.5 5H10V6H2V10H10V11H1.5L1 10.5Z" fill="#C5C5C5"/>
<path d="M13 5H14.5L15 5.5V10.5L14.5 11H13V10H14V6H13V5Z" fill="#C5C5C5"/>
<path d="M3 7.5V8.5L3.5 9H7.5L8 8.5V7.5L7.5 7H3.5L3 7.5Z" fill="#C5C5C5"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 2.3 KiB

После

Ширина:  |  Высота:  |  Размер: 520 B

Просмотреть файл

@ -719,19 +719,19 @@
}
},
{
"command" : "C_Cpp.referencesViewGroupByType",
"command": "C_Cpp.referencesViewGroupByType",
"title": "%c_cpp.command.referencesViewGroupByType.title%",
"icon" : {
"light": "assets/ref-group-by-type-light.svg",
"dark": "assets/ref-group-by-type-dark.svg"
"icon": {
"light": "assets/ref-group-by-type-light.svg",
"dark": "assets/ref-group-by-type-dark.svg"
}
},
{
"command" : "C_Cpp.referencesViewGroupByFile",
"command": "C_Cpp.referencesViewGroupByFile",
"title": "%c_cpp.command.referencesViewGroupByFile.title%",
"icon" : {
"light": "assets/ref-group-by-file-light.svg",
"dark": "assets/ref-group-by-file-dark.svg"
"icon": {
"light": "assets/ref-group-by-file-light.svg",
"dark": "assets/ref-group-by-file-dark.svg"
}
}
],

Просмотреть файл

@ -286,8 +286,14 @@ let failureMessageShown: boolean = false;
let referencesRequestPending: boolean = false;
let renamePending: boolean = false;
let referencesParams: any;
let referencesPromiseReject: any;
let referencesParams: RenameParams | FindAllReferencesParams;
interface ReferencesCancellationState {
reject(): void;
callback(): void;
}
let referencesPendingCancellations: ReferencesCancellationState[] = [];
interface ClientModel {
isTagParsing: DataBinding<boolean>;
@ -606,57 +612,69 @@ export class DefaultClient implements Client {
this.client = client;
}
public async provideReferences(document: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext, token: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
if (referencesRequestPending) {
referencesRequestPending = false;
this.client.references.closeRenameUI();
this.client.cancelReferences();
referencesPromiseReject();
}
renamePending = false;
let params: FindAllReferencesParams = {
position: Position.create(position.line, position.character),
textDocument: this.client.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document)
};
referencesParams = params;
return new Promise<vscode.Location[]>((resolve, reject) => {
this.client.notifyWhenReady(() => {
// The current request is represented by referencesParams. If a request detects
// referencesParams does not match the object used when creating the request, abort it.
if (params !== referencesParams) {
reject();
}
referencesPromiseReject = reject;
referencesRequestPending = true;
this.client.languageClient.sendNotification(FindAllReferencesNotification, params);
// Register a single-fire handler for the reply.
this.client.references.setResultsCallback(result => {
if (referencesRequestPending) {
let callback: () => void = () => {
let params: FindAllReferencesParams = {
position: Position.create(position.line, position.character),
textDocument: this.client.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document)
};
referencesParams = params;
this.client.notifyWhenReady(() => {
// The current request is represented by referencesParams. If a request detects
// referencesParams does not match the object used when creating the request, abort it.
if (params !== referencesParams) {
reject();
return;
}
referencesRequestPending = true;
this.client.languageClient.sendNotification(FindAllReferencesNotification, params);
// Register a single-fire handler for the reply.
this.client.references.setResultsCallback((final, result) => {
referencesRequestPending = false;
let locations: vscode.Location[] = [];
result.referenceInfos.forEach(referenceInfo => {
if (referenceInfo.type === refs.ReferenceType.Confirmed) {
let uri: vscode.Uri = vscode.Uri.file(referenceInfo.file);
let range: vscode.Range = new vscode.Range(referenceInfo.position.line, referenceInfo.position.character, referenceInfo.position.line, referenceInfo.position.character + result.text.length);
locations.push(new vscode.Location(uri, range));
let cancelling: boolean = referencesPendingCancellations.length > 0;
if (cancelling) {
if (final) {
reject();
while (referencesPendingCancellations.length > 1) {
let pendingCancel: ReferencesCancellationState = referencesPendingCancellations[0];
referencesPendingCancellations.pop();
pendingCancel.reject();
}
let pendingCancel: ReferencesCancellationState = referencesPendingCancellations[0];
referencesPendingCancellations.pop();
pendingCancel.callback();
}
});
resolve(locations);
} else {
let locations: vscode.Location[] = [];
result.referenceInfos.forEach(referenceInfo => {
if (referenceInfo.type === refs.ReferenceType.Confirmed) {
let uri: vscode.Uri = vscode.Uri.file(referenceInfo.file);
let range: vscode.Range = new vscode.Range(referenceInfo.position.line, referenceInfo.position.character, referenceInfo.position.line, referenceInfo.position.character + result.text.length);
locations.push(new vscode.Location(uri, range));
}
});
resolve(locations);
}
});
});
token.onCancellationRequested(e => {
if (params === referencesParams) {
this.client.cancelReferences();
}
});
});
token.onCancellationRequested(e => {
if (params === referencesParams) {
if (referencesRequestPending) {
referencesRequestPending = false;
this.client.cancelReferences();
this.client.sendRequestReferences();
reject();
} else {
referencesParams = null;
}
};
if (referencesRequestPending) {
let cancelling: boolean = referencesPendingCancellations.length > 0;
referencesPendingCancellations.push({ reject, callback });
if (!cancelling) {
renamePending = false;
this.client.languageClient.sendNotification(CancelReferencesNotification);
this.client.references.closeRenameUI();
}
});
} else {
callback();
}
});
}
}
@ -674,47 +692,64 @@ export class DefaultClient implements Client {
// Because that prevents our rename UI, we ignore cancellation requests.
// VS Code will attempt to issue new rename requests while another is still active.
// When we receive another rename request, cancel the one that is in progress.
if (referencesRequestPending) {
this.client.references.closeRenameUI();
this.client.cancelReferences();
referencesPromiseReject();
}
renamePending = true;
let params: RenameParams = {
newName: newName,
position: Position.create(position.line, position.character),
textDocument: this.client.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document)
};
referencesParams = params;
referencesRequestPending = false;
return new Promise<vscode.WorkspaceEdit>((resolve, reject) => {
this.client.notifyWhenReady(() => {
// The current request is represented by referencesParams. If a request detects
// referencesParams does not match the object used when creating the request, abort it.
if (params !== referencesParams) {
reject();
}
referencesPromiseReject = reject;
referencesRequestPending = true;
this.client.languageClient.sendNotification(RenameNotification, params);
this.client.references.setResultsCallback(referencesResult => {
referencesRequestPending = false;
renamePending = false;
let workspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
// If rename UI Was cancelled, we will get a null result
// If null, return an empty list to avoid Rename failure dialog
if (referencesResult !== null) {
for (let reference of referencesResult.referenceInfos) {
let uri: vscode.Uri = vscode.Uri.file(reference.file);
let range: vscode.Range = new vscode.Range(reference.position.line, reference.position.character, reference.position.line, reference.position.character + referencesResult.text.length);
workspaceEdit.replace(uri, range, newName);
}
let callback: () => void = () => {
let params: RenameParams = {
newName: newName,
position: Position.create(position.line, position.character),
textDocument: this.client.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document)
};
referencesParams = params;
this.client.notifyWhenReady(() => {
// The current request is represented by referencesParams. If a request detects
// referencesParams does not match the object used when creating the request, abort it.
if (params !== referencesParams) {
reject();
return;
}
this.client.references.closeRenameUI();
resolve(workspaceEdit);
referencesRequestPending = true;
this.client.languageClient.sendNotification(RenameNotification, params);
this.client.references.setResultsCallback((final, referencesResult) => {
referencesRequestPending = false;
let workspaceEdit: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
let cancelling: boolean = referencesPendingCancellations.length > 0;
if (cancelling) {
while (referencesPendingCancellations.length > 1) {
let pendingCancel: ReferencesCancellationState = referencesPendingCancellations[0];
referencesPendingCancellations.pop();
pendingCancel.reject();
}
let pendingCancel: ReferencesCancellationState = referencesPendingCancellations[0];
referencesPendingCancellations.pop();
pendingCancel.callback();
} else {
// If rename UI Was cancelled, we will get a null result
// If null, return an empty list to avoid Rename failure dialog
if (referencesResult !== null) {
for (let reference of referencesResult.referenceInfos) {
let uri: vscode.Uri = vscode.Uri.file(reference.file);
let range: vscode.Range = new vscode.Range(reference.position.line, reference.position.character, reference.position.line, reference.position.character + referencesResult.text.length);
workspaceEdit.replace(uri, range, newName);
}
}
this.client.references.closeRenameUI();
}
resolve(workspaceEdit);
});
});
});
};
if (referencesRequestPending) {
let cancelling: boolean = referencesPendingCancellations.length > 0;
referencesPendingCancellations.push({ reject, callback });
if (!cancelling) {
this.client.languageClient.sendNotification(CancelReferencesNotification);
this.client.references.closeRenameUI();
}
} else {
callback();
}
});
}
}
@ -929,14 +964,7 @@ export class DefaultClient implements Client {
// If any file has changed, we need to abort the current rename operation
if (renamePending) {
renamePending = false;
referencesParams = null;
if (referencesRequestPending) {
referencesRequestPending = false;
this.references.closeRenameUI();
this.cancelReferences();
referencesPromiseReject();
}
this.cancelReferences();
}
let oldVersion: number = this.openFileVersions.get(textDocumentChangeEvent.document.uri.toString());
@ -2088,9 +2116,12 @@ export class DefaultClient implements Client {
public handleReferencesIcon(): void {
this.notifyWhenReady(() => {
this.references.UpdateProgressUICounter(this.model.referencesCommandMode.Value);
if (this.ReferencesCommandMode === refs.ReferencesCommandMode.Find) {
this.sendRequestReferences();
let cancelling: boolean = referencesPendingCancellations.length > 0;
if (!cancelling) {
this.references.UpdateProgressUICounter(this.model.referencesCommandMode.Value);
if (this.ReferencesCommandMode === refs.ReferencesCommandMode.Find) {
this.sendRequestReferences();
}
}
});
}
@ -2120,7 +2151,16 @@ export class DefaultClient implements Client {
}
public cancelReferences(): void {
this.languageClient.sendNotification(CancelReferencesNotification);
referencesParams = null;
renamePending = false;
if (referencesRequestPending) {
let cancelling: boolean = referencesPendingCancellations.length > 0;
if (!cancelling) {
referencesPendingCancellations.push({ reject: () => {}, callback: () => {} });
this.languageClient.sendNotification(CancelReferencesNotification);
this.references.closeRenameUI();
}
}
}
private handleReferencesProgress(notificationBody: refs.ReportReferencesProgressNotification): void {

Просмотреть файл

@ -44,8 +44,6 @@ enum ReferencesProgress {
StartedRename,
ProcessingSource,
ProcessingTargets,
CanceledFinalResultsAvailable,
FinalResultsAvailable,
Finished
}
@ -111,7 +109,7 @@ export function convertReferenceTypeToString(referenceType: ReferenceType, upper
function getReferenceCanceledString(upperCase?: boolean): string {
return upperCase ?
localize("confirmation.canceled", "CONFIRMATION CANCELED") :
localize("confirmation.canceled.upper", "CONFIRMATION CANCELED") :
localize("confirmation.canceled", "Confirmation canceled");
}
@ -150,7 +148,10 @@ export class ReferencesManager {
private visibleRangesDecreasedTicks: number = 0;
private readonly ticksForDetectingPeek: number = 1000; // TODO: Might need tweeking?
private resultsCallback: (results: ReferencesResult) => void;
private resultsCallback: (final: boolean, results: ReferencesResult) => void;
private currentUpdateProgressTimer: NodeJS.Timeout;
private currentUpdateProgressResolve: () => void;
private lastResult: ReferencesResult;
constructor(client: DefaultClient) {
this.client = client;
@ -258,10 +259,6 @@ export class ReferencesManager {
this.referencesPrevProgressMessage = currentMessage;
}
break;
case ReferencesProgress.CanceledFinalResultsAvailable:
case ReferencesProgress.FinalResultsAvailable:
progress.report({ message: localize("finished", "Finished."), increment: 100 });
break;
}
}
@ -279,26 +276,28 @@ export class ReferencesManager {
this.referencesPrevProgressIncrement = 0;
this.referencesPrevProgressMessage = "";
this.referencesCurrentProgressUICounter = 0;
this.currentUpdateProgressTimer = null;
this.currentUpdateProgressResolve = null;
let referencePreviousProgressUICounter: number = 0;
this.clearViews();
this.referencesDelayProgress = setInterval(() => {
this.referencesProgressOptions = { location: vscode.ProgressLocation.Notification, title: referencesCommandModeToString(this.client.ReferencesCommandMode), cancellable: true };
this.referencesProgressMethod = (progress: vscode.Progress<{message?: string; increment?: number }>, token: vscode.CancellationToken) =>
// tslint:disable-next-line: promise-must-complete
new Promise((resolve) => {
this.currentUpdateProgressResolve = resolve;
this.reportProgress(progress, true, mode);
let currentUpdateProgressTimer: NodeJS.Timeout = setInterval(() => {
this.currentUpdateProgressTimer = setInterval(() => {
if (token.isCancellationRequested && !this.referencesCanceled) {
this.client.cancelReferences();
if (this.client.ReferencesCommandMode !== ReferencesCommandMode.Rename) {
this.client.sendRequestReferences();
}
this.referencesCanceled = true;
}
if (this.referencesCurrentProgress.referencesProgress === ReferencesProgress.Finished || this.referencesCurrentProgressUICounter !== referencePreviousProgressUICounter) {
clearInterval(currentUpdateProgressTimer);
clearInterval(this.currentUpdateProgressTimer);
this.currentUpdateProgressTimer = null;
if (this.referencesCurrentProgressUICounter !== referencePreviousProgressUICounter) {
referencePreviousProgressUICounter = this.referencesCurrentProgressUICounter;
this.referencesPrevProgressIncrement = 0; // Causes update bar to not reset.
@ -326,18 +325,21 @@ export class ReferencesManager {
}
this.handleProgressStarted(notificationBody.referencesProgress);
break;
case ReferencesProgress.CanceledFinalResultsAvailable:
case ReferencesProgress.FinalResultsAvailable:
if (notificationBody.referencesProgress === ReferencesProgress.CanceledFinalResultsAvailable) {
this.referencesCanceled = true;
}
this.referencesCurrentProgress = notificationBody;
this.client.sendRequestReferences();
break;
case ReferencesProgress.Finished:
this.referencesCurrentProgress = notificationBody;
this.client.setReferencesCommandMode(ReferencesCommandMode.None);
clearInterval(this.referencesDelayProgress);
if (this.currentUpdateProgressTimer) {
clearInterval(this.currentUpdateProgressTimer);
this.currentUpdateProgressResolve();
this.currentUpdateProgressResolve = null;
}
if (this.client.ReferencesCommandMode !== ReferencesCommandMode.Rename) {
let callback: (final: boolean, result: ReferencesResult) => void = this.resultsCallback;
this.resultsCallback = null;
callback(true, this.lastResult);
this.lastResult = null;
}
this.client.setReferencesCommandMode(ReferencesCommandMode.None);
break;
default:
this.referencesCurrentProgress = notificationBody;
@ -363,7 +365,7 @@ export class ReferencesManager {
// If there are only Confirmed results, complete the rename immediately.
let foundUnconfirmed: ReferenceInfo = referencesResult.referenceInfos.find(e => e.type !== ReferenceType.Confirmed);
if (!foundUnconfirmed) {
this.resultsCallback(referencesResult);
this.resultsCallback(true, referencesResult);
} else {
this.renameView.show(true);
this.renameView.setData(referencesResult, this.resultsCallback);
@ -375,10 +377,7 @@ export class ReferencesManager {
// Display data based on command mode: peek references OR find all references
if (this.client.ReferencesCommandMode === ReferencesCommandMode.Peek) {
// Show confirmed references if: user previews results OR peek references is canceled
let showConfirmedReferences: boolean =
(!this.referencesCanceled && this.referencesCurrentProgress.referencesProgress !== ReferencesProgress.FinalResultsAvailable)
|| (this.referencesCanceled && this.referencesCurrentProgress.referencesProgress === ReferencesProgress.CanceledFinalResultsAvailable);
let showConfirmedReferences: boolean = this.referencesCanceled;
let peekReferencesResults: string = this.findAllRefsView.getResultsAsText(showConfirmedReferences);
if (peekReferencesResults) {
this.referencesChannel.appendLine(peekReferencesResults);
@ -387,11 +386,12 @@ export class ReferencesManager {
} else if (this.client.ReferencesCommandMode === ReferencesCommandMode.Find) {
this.findAllRefsView.show(true);
}
this.resultsCallback(referencesResult);
this.lastResult = referencesResult;
this.resultsCallback(false, referencesResult);
}
}
public setResultsCallback(callback: (results: ReferencesResult) => void): void {
public setResultsCallback(callback: (final: boolean, results: ReferencesResult) => void): void {
this.resultsCallback = callback;
}

Просмотреть файл

@ -237,10 +237,10 @@ let currentRenameModel: RenameModel;
export class RenameModel {
private pendingGroup: RenamePendingFilesGroupItem;
private candidatesGroup: RenameCandidateReferenceTypeGroupItem;
private renameResultsCallback: (results: ReferencesResult) => void;
private renameResultsCallback: (final: boolean, results: ReferencesResult) => void;
private originalText: string;
constructor(resultsInput: ReferencesResult, readonly pendingProvider: RenameDataProvider, readonly candidateProvider: RenameDataProvider, resultsCallback: (results: ReferencesResult) => void) {
constructor(resultsInput: ReferencesResult, readonly pendingProvider: RenameDataProvider, readonly candidateProvider: RenameDataProvider, resultsCallback: (final: boolean, results: ReferencesResult) => void) {
currentRenameModel = this;
this.originalText = resultsInput.text;
this.renameResultsCallback = resultsCallback;
@ -283,7 +283,11 @@ export class RenameModel {
}
cancel(): void {
this.renameResultsCallback(null);
if (this.renameResultsCallback) {
let callback: (final: boolean, results: ReferencesResult) => void = this.renameResultsCallback;
this.renameResultsCallback = null;
callback(true, null);
}
}
complete(): void {
@ -303,7 +307,9 @@ export class RenameModel {
text: this.originalText,
referenceInfos: referenceInfos
};
this.renameResultsCallback(results);
let callback: (final: boolean, results: ReferencesResult) => void = this.renameResultsCallback;
this.renameResultsCallback = null;
callback(true, results);
}
}

Просмотреть файл

@ -11,6 +11,8 @@ import { RenameModel } from './renameModel';
export class RenameView {
private renamePendingDataProvider: RenameDataProvider;
private renameCandidatesDataProvider: RenameDataProvider;
private model: RenameModel;
private visible: boolean = false;
constructor() {
this.renamePendingDataProvider = new RenameDataProvider(true);
@ -27,16 +29,20 @@ export class RenameView {
show(showView: boolean): void {
vscode.commands.executeCommand(`setContext`, 'cppRename:hasResults', showView);
if (showView) {
this.visible = true;
vscode.commands.executeCommand(`CppRenamePendingView.focus`);
} else {
} else if (this.visible) {
this.visible = false;
this.model.cancel();
this.model = null;
this.clearData();
}
}
setData(results: ReferencesResult, resultsCallback: (results: ReferencesResult) => void): void {
let renameModel: RenameModel = new RenameModel(results, this.renamePendingDataProvider, this.renameCandidatesDataProvider, resultsCallback);
this.renamePendingDataProvider.setModel(renameModel);
this.renameCandidatesDataProvider.setModel(renameModel);
setData(results: ReferencesResult, resultsCallback: (final: boolean, results: ReferencesResult) => void): void {
this.model = new RenameModel(results, this.renamePendingDataProvider, this.renameCandidatesDataProvider, resultsCallback);
this.renamePendingDataProvider.setModel(this.model);
this.renameCandidatesDataProvider.setModel(this.model);
}
clearData(): void {