Skip to content

Commit 2a6c0fc

Browse files
authored
fix: Lose refresh events when debouncing (#633)
Signed-off-by: sheche <[email protected]>
1 parent 317bd63 commit 2a6c0fc

File tree

7 files changed

+50
-20
lines changed

7 files changed

+50
-20
lines changed

src/commands.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export namespace Commands {
2020

2121
export const VIEW_PACKAGE_REFRESH = "java.view.package.refresh";
2222

23+
export const VIEW_PACKAGE_INTERNAL_REFRESH = "_java.view.package.internal.refresh";
24+
2325
export const VIEW_PACKAGE_OUTLINE = "java.view.package.outline";
2426

2527
export const VIEW_PACKAGE_REVEAL_FILE_OS = "java.view.package.revealFileInOS";

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function addExtensionChangeListener(context: ExtensionContext): void {
5252
// java language support is not installed or disabled
5353
const extensionChangeListener = extensions.onDidChange(() => {
5454
if (extensions.getExtension(ExtensionName.JAVA_LANGUAGE_SUPPORT)) {
55-
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */false);
55+
commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */false);
5656
extensionChangeListener.dispose();
5757
}
5858
});

src/languageServerApi/languageServerApiManager.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ class LanguageServerApiManager {
5252
if (extensionApi.onDidClasspathUpdate) {
5353
const onDidClasspathUpdate: Event<Uri> = extensionApi.onDidClasspathUpdate;
5454
contextManager.context.subscriptions.push(onDidClasspathUpdate(() => {
55-
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */true);
55+
commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true);
5656
syncHandler.updateFileWatcher(Settings.autoRefresh());
5757
}));
5858
}
5959

6060
if (extensionApi.onDidProjectsImport) {
6161
const onDidProjectsImport: Event<Uri[]> = extensionApi.onDidProjectsImport;
6262
contextManager.context.subscriptions.push(onDidProjectsImport(() => {
63-
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */true);
63+
commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true);
6464
syncHandler.updateFileWatcher(Settings.autoRefresh());
6565
}));
6666
}
@@ -70,7 +70,7 @@ class LanguageServerApiManager {
7070
const onDidServerModeChange: Event<string> = extensionApi.onDidServerModeChange;
7171
contextManager.context.subscriptions.push(onDidServerModeChange((mode: LanguageServerMode) => {
7272
if (mode === LanguageServerMode.Hybrid) {
73-
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */false);
73+
commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */false);
7474
}
7575
}));
7676
}

src/settings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export class Settings {
2727
|| updatedConfig.packagePresentation !== oldConfig.packagePresentation
2828
|| (updatedConfig.syncWithFolderExplorer !== oldConfig.syncWithFolderExplorer
2929
&& updatedConfig.syncWithFolderExplorer)) {
30-
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH);
30+
commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH);
3131
} else if (updatedConfig.autoRefresh !== oldConfig.autoRefresh) {
3232
syncHandler.updateFileWatcher(updatedConfig.autoRefresh);
3333
}

src/syncHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class SyncHandler implements Disposable {
118118
}
119119

120120
private refresh(node?: ExplorerNode): void {
121-
commands.executeCommand(Commands.VIEW_PACKAGE_REFRESH, /* debounce = */true, node);
121+
commands.executeCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, /* debounce = */true, node);
122122
}
123123
}
124124

src/views/dependencyDataProvider.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
commands, Event, EventEmitter, ExtensionContext, ProviderResult,
77
RelativePattern, TreeDataProvider, TreeItem, Uri, window, workspace,
88
} from "vscode";
9-
import { instrumentOperation, instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper";
9+
import { instrumentOperationAsVsCodeCommand } from "vscode-extension-telemetry-wrapper";
1010
import { contextManager } from "../../extension.bundle";
1111
import { Commands } from "../commands";
1212
import { Context } from "../constants";
@@ -31,13 +31,24 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
3131

3232
private _rootItems: ExplorerNode[] | undefined = undefined;
3333
private _refreshDelayTrigger: _.DebouncedFunc<((element?: ExplorerNode) => void)>;
34+
/**
35+
* The element which is pending to be refreshed.
36+
* `undefined` denotes to root node.
37+
* `null` means no node is pending.
38+
*/
39+
private pendingRefreshElement: ExplorerNode | undefined | null;
3440

3541
constructor(public readonly context: ExtensionContext) {
36-
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_REFRESH, (debounce?: boolean, element?: ExplorerNode) =>
37-
this.refreshWithLog(debounce, element)));
42+
// commands that do not send back telemetry
43+
context.subscriptions.push(commands.registerCommand(Commands.VIEW_PACKAGE_INTERNAL_REFRESH, (debounce?: boolean, element?: ExplorerNode) =>
44+
this.refresh(debounce, element)));
3845
context.subscriptions.push(commands.registerCommand(Commands.EXPORT_JAR_REPORT, (terminalId: string, message: string) => {
3946
appendOutput(terminalId, message);
4047
}));
48+
49+
// normal commands
50+
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_REFRESH, (debounce?: boolean, element?: ExplorerNode) =>
51+
this.refresh(debounce, element)));
4152
context.subscriptions.push(instrumentOperationAsVsCodeCommand(Commands.VIEW_PACKAGE_EXPORT_JAR, async (node: INodeData) => {
4253
executeExportJarTask(node);
4354
}));
@@ -61,28 +72,33 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
6172

6273
Settings.registerConfigurationListener((updatedConfig, oldConfig) => {
6374
if (updatedConfig.refreshDelay !== oldConfig.refreshDelay) {
64-
this.setRefreshDelay(updatedConfig.refreshDelay);
75+
this.setRefreshDebounceFunc(updatedConfig.refreshDelay);
6576
}
6677
});
67-
this.setRefreshDelay();
78+
this.setRefreshDebounceFunc();
6879
}
6980

70-
public refreshWithLog(debounce?: boolean, element?: ExplorerNode) {
71-
if (Settings.autoRefresh()) {
72-
this.refresh(debounce, element);
81+
public refresh(debounce = false, element?: ExplorerNode) {
82+
if (element === undefined || this.pendingRefreshElement === undefined) {
83+
this._refreshDelayTrigger(undefined);
84+
this.pendingRefreshElement = undefined;
85+
} else if (this.pendingRefreshElement === null
86+
|| element.isItselfOrAncestorOf(this.pendingRefreshElement)) {
87+
this._refreshDelayTrigger(element);
88+
this.pendingRefreshElement = element;
89+
} else if (this.pendingRefreshElement.isItselfOrAncestorOf(element)) {
90+
this._refreshDelayTrigger(this.pendingRefreshElement);
7391
} else {
74-
instrumentOperation(Commands.VIEW_PACKAGE_REFRESH, () => this.refresh(debounce, element))();
92+
this._refreshDelayTrigger.flush();
93+
this._refreshDelayTrigger(element);
94+
this.pendingRefreshElement = element;
7595
}
76-
}
77-
78-
public refresh(debounce = false, element?: ExplorerNode) {
79-
this._refreshDelayTrigger(element);
8096
if (!debounce) { // Immediately refresh
8197
this._refreshDelayTrigger.flush();
8298
}
8399
}
84100

85-
public setRefreshDelay(wait?: number) {
101+
public setRefreshDebounceFunc(wait?: number) {
86102
if (!wait) {
87103
wait = Settings.refreshDelay();
88104
}
@@ -142,6 +158,7 @@ export class DependencyDataProvider implements TreeDataProvider<ExplorerNode> {
142158
}
143159
explorerNodeCache.removeNodeChildren(element);
144160
this._onDidChangeTreeData.fire(element);
161+
this.pendingRefreshElement = null;
145162
}
146163

147164
private async getRootNodes(): Promise<ExplorerNode[]> {

src/views/explorerNode.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ export abstract class ExplorerNode {
1212
return this._parent;
1313
}
1414

15+
public isItselfOrAncestorOf(node: ExplorerNode | undefined | null) {
16+
while (node) {
17+
if (this === node) {
18+
return true;
19+
}
20+
node = node.getParent();
21+
}
22+
23+
return false;
24+
}
25+
1526
protected get command(): Command | undefined {
1627
return undefined;
1728
}

0 commit comments

Comments
 (0)