Skip to content

Conversation

@shouples
Copy link
Contributor

@shouples shouples commented Oct 3, 2025

Summary of Changes

No functional changes here, just getting one step closer toward closing #1498 and setting the rule to error.

On main, this rule shows ~180 violations, but this branch takes care of the majority of them, to the point where we can set the rule to warn without reaching the warn-limit (50) and causing CI to fail static analysis.
image

Takeaways:

  • most offenders were calls to logError(), which was previously an async function, but is now a synchronous function wrapping the async logic with a basic .catch() so all callers don't need to explicitly await or void
  • the next largest group of offenders were anything involving show*NotificationWithButtons(), which now also use void since the vast majority of the time we don't need to block on the underlying window.show[Information|Warning|Error]Message() or its (potentially-async) button callbacks
  • after that, awaits were needed in tests either for assert.rejects or in the test logic where an async function / class method was being called
  • remaining specific areas that needed fixing have specific PR comments for explanations/context

Pull request checklist

Please check if your PR fulfills the following (if applicable):

Tests

  • Added new
  • Updated existing
  • Deleted existing

Release notes

  • Does anything in this PR need to be mentioned in the user-facing CHANGELOG?

// Don't send with undefined settings, server will override existing settings with empty/undefined values
if (settings.databaseName && settings.computePoolId && settings.catalogName) {
this.languageClient.sendNotification("workspace/didChangeConfiguration", {
await this.languageClient.sendNotification("workspace/didChangeConfiguration", {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@noeldevelops I'm assuming we want to await this, right?

Copy link
Member

Choose a reason for hiding this comment

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

yes please!

await languageClient.start();
logger.debug("FlinkSQL Language Server started");
languageClient.setTrace(Trace.Compact);
await languageClient.setTrace(Trace.Compact);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

(cc @noeldevelops this also seemed fine to await instead of void)

Copy link
Member

Choose a reason for hiding this comment

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

it doesn't return anything so void is ok here I think? It is a Promise though

Comment on lines +64 to +66
for (const value of [false, undefined]) {
it(`hasCCloudAuthSession() should return false when the context value is ${value}`, async () => {
await setContextValue(ContextValues.ccloudConnectionAvailable, value);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Split to an outer-for loop so the dynamically-created tests could be made async instead of dealing with "await-in-for-loop"


// As if had been just sent from sidecar.
connectionStateWatcher.handleConnectionUpdateEvent(websocketMessage);
await connectionStateWatcher.handleConnectionUpdateEvent(websocketMessage);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was the main offender in the file, but then required the test-callers to await its containing function


/** Called whenever websocket connection goes CONNECTED or DISCONNECTED. */
private onWebsocketStateChange(event: WebsocketStateEvent) {
private async onWebsocketStateChange(event: WebsocketStateEvent) {
Copy link
Contributor Author

@shouples shouples Oct 3, 2025

Choose a reason for hiding this comment

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

Only caller is a few lines up, in the event listener callback binding:

this.websocketManager.registerStateChangeHandler(this.onWebsocketStateChange.bind(this));

Comment on lines 112 to +114
it("should await for release", async () => {
const { acquire, release } = semaphore(1);
acquire();
await acquire();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This one was a little ironic

Copy link
Contributor

Choose a reason for hiding this comment

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

Sigh.

void logError(new Error(msg, { cause: e }), msg, { extra: {} });
}
closeSentryClient();
void closeSentryClient();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not trying to await or catch errors during disposal, cc @noeldevelops

Comment on lines -222 to -223
topicViewProvider.reset();
schemasViewProvider.reset();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jlrobins do you think we should expand this behavior to the rest of the views, or remove this entirely?

I don't know if this is even necessary anymore since we still wipe workspace state on activation, but the only area this might cause issues is during extension version updates where the Topics and Schemas views may reset in the middle of use (from one extension version to another). I don't think we've tested that path for the Flink-related views though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, good question, but at least not needing answering here in for this branch.

I think that it'd be safer to include to do for all views (but not needed in this branch).

Comment on lines 226 to +234
for (const instance of getRefreshableViewProviders()) {
refreshCommands.push(
registerCommandWithLogging(`confluent.${instance.kind}.refresh`, (): boolean => {
instance.refresh(true);
return true;
}),
registerCommandWithLogging(
`confluent.${instance.kind}.refresh`,
async (): Promise<boolean> => {
await instance.refresh(true);
return true;
},
),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

View-level refreshing still working as expected ✅

Comment on lines +403 to +409
await this.submitSearch(value);
} else {
// otherwise, we keep debouncing search submittion until the user stops typing
if (this.searchTimer != null) clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(async () => {
const value = target.value.trim();
this.submitSearch(value);
await this.submitSearch(value);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Flink statement result search still seems to behave as expected, but I'm curious if there are any nuances here with timing/performance we need to be cautious handling.

docChangeSub.dispose();
docSaveSub.dispose();
validateDocument(documentUri, schema);
await validateDocument(documentUri, schema);
Copy link
Contributor Author

@shouples shouples Oct 3, 2025

Choose a reason for hiding this comment

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

Produce-message validation still happening as expected on document content change ✅

docChangeSub.dispose();
docSaveSub.dispose();
validateDocument(documentUri, schema);
await validateDocument(documentUri, schema);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This one is harder to test since validation errors will persist before/after a document is saved, but nothing out of the ordinary is happening after this change

@shouples shouples marked this pull request as ready for review October 3, 2025 19:52
@shouples shouples requested a review from a team as a code owner October 3, 2025 19:52
Copilot AI review requested due to automatic review settings October 3, 2025 19:52
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR addresses the no-floating-promises ESLint rule violations by ensuring promises are properly handled throughout the codebase. The changes focus on either awaiting promises where appropriate or using void for fire-and-forget operations.

Key Changes:

  • Added await keywords for promises that need to be awaited, particularly in tests and critical code paths
  • Used void prefix for fire-and-forget operations like logging and notifications
  • Updated test methods to be async where promise handling is required

Reviewed Changes

Copilot reviewed 67 out of 67 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
eslint.config.mjs Enabled no-floating-promises rule as warning with TypeScript parser configuration
src/extension.ts Fixed promise handling in extension activation and deactivation
src/notifications.ts Added void prefix for error logging in notification callbacks
src/viewProviders/topics.test.ts Made test methods async and added await for async handlers
src/viewProviders/schemas.ts Added void prefix for error logging
src/sidecar/ files Consistent void prefixing for logError calls
src/commands/ files Added void prefixes for notification and logging calls
src/flinkSql/ files Fixed promise handling in language client and statement management
src/featureFlags/ files Added void prefixes for error logging
src/utils/ files Fixed test assertions and worker pool error handling
src/webview/ files Added await for async operations in form handling
Various test files Made test methods async and added await for assert.rejects

@sonarqube-confluent
Copy link

Failed

  • 67.90% Coverage on New Code (is less than 80.00%)

Analysis Details

2 Issues

  • Bug 0 Bugs
  • Vulnerability 0 Vulnerabilities
  • Code Smell 2 Code Smells

Coverage and Duplications

  • Coverage 67.90% Coverage (72.10% Estimated after merge)
  • Duplications No duplication information (0.60% Estimated after merge)

Project ID: vscode

View in SonarQube

@jlrobins jlrobins self-assigned this Oct 3, 2025
Copy link
Contributor

@jlrobins jlrobins left a comment

Choose a reason for hiding this comment

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

Things still work! Excellent, thanks!

Comment on lines -222 to -223
topicViewProvider.reset();
schemasViewProvider.reset();
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, good question, but at least not needing answering here in for this branch.

I think that it'd be safer to include to do for all views (but not needed in this branch).

@shouples shouples merged commit e016882 into main Oct 3, 2025
13 of 14 checks passed
@shouples shouples deleted the djs/no-floating-promises-fix1 branch October 3, 2025 21:14
@sentry
Copy link

sentry bot commented Oct 10, 2025

Issues attributed to commits in this pull request

This pull request was merged and Sentry observed the following issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants