Skip to content

feat(Buildifier): Allow enabling /disabling buildifier functionality #629

Open
cbandera wants to merge 8 commits into
bazel-contrib:masterfrom
cbandera:feature/490-buildifier-feature
Open

feat(Buildifier): Allow enabling /disabling buildifier functionality #629
cbandera wants to merge 8 commits into
bazel-contrib:masterfrom
cbandera:feature/490-buildifier-feature

Conversation

@cbandera

@cbandera cbandera commented May 3, 2026

Copy link
Copy Markdown
Collaborator

Description

  • Add BuildifierFeature class extending BaseExtensionFeature
  • Add bazel.enableBuildifier configuration setting (default: true)
  • Move buildifier diagnostics and formatting provider registration into feature
  • Extract showBuildifierDownloadPrompt for async user notifications
  • Remove duplicate buildifier availability checks from extension.ts
  • Maintain backward compatibility with existing buildifier functionality
  • Make buildifier feature independent of the presence of a bazel workspace (now uses absolute paths)

This change encapsulates buildifier support as a toggleable feature following the same patterns as CodeLensFeature and WorkspaceTreeFeature.

Related Issue

Related to #490
Closes #193
Related to #402
Closes #449
Closes #620

Testing

  • Tests added/updated
  • Manual testing performed

Checklist

  • Code follows the project's style guidelines (prettier/eslint)
  • Commit messages follow Conventional Commit conventions
  • Tests pass locally (npm run test)

cbandera added 3 commits May 11, 2026 20:24
- Add BuildifierFeature class extending BaseExtensionFeature
- Add bazel.enableBuildifier configuration setting (default: true)
- Move buildifier diagnostics and formatting provider registration into feature
- Extract showBuildifierDownloadPrompt for async user notifications
- Remove duplicate buildifier availability checks from extension.ts
- Maintain backward compatibility with existing buildifier functionality

This change encapsulates buildifier support as a toggleable feature following
the same patterns as CodeLensFeature and WorkspaceTreeFeature.
This has multiple positive effects:
- buildifier can be used on any Starlark file even if not bazel workspace is present
- buildifier can be used on standalone files outside your current workspace
- buildifier will work robustly for multi-workspace setups

Closes bazel-contrib#620
@cbandera cbandera force-pushed the feature/490-buildifier-feature branch from 6d823ef to 3fd9ddf Compare May 11, 2026 18:25
Comment thread package.json
@cbandera cbandera changed the title feat(buildifier): convert buildifier support to ExtensionFeature feat(Buildifier): Allow enabling /disabling buildifier functionality May 12, 2026
Comment thread src/buildifier/buildifier_feature.ts Outdated

enable(context: vscode.ExtensionContext): boolean {
// Precondition: buildifier executable available
if (!checkBuildifierIsAvailable()) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The checkBuildifierIsAvailable function is async so this condition will always evaluate to false (since a promise is truthy). Is it viable for this function to be async?

This would have been caught if we had the no-misused-promises eslint option enabled. I'll put up a PR to enable this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks. I will need to think about the best design for this a little longer

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Made the enable() function async, which however also made it necessary to avoid race conditions with multiple config changes while a enable call is still running.

cameron-martin added a commit that referenced this pull request May 18, 2026
This rule would have caught an issue with #629 if it were enabled, particularly the `checksConditionals` part. A few modifications had to be made to accommodate the `checksVoidReturn` part of the rule.
cbandera added 5 commits May 18, 2026 22:28
checkBuildifierIsAvailable() is async but was called without await, so
the truthy Promise always passed the guard — buildifier was never actually
checked. Fix by making enable() return Promise<boolean> across the base
class and all subclasses, and propagating async through
onConfigurationChanged and the create() factory.
…andling

  - Serialize onConfigurationChanged calls via a pending-promise chain to
    prevent concurrent enable() invocations and lost disable-while-enabling
  - Catch exceptions thrown by enable() in doConfigurationChange so OS-level
    errors (EACCES, spawn failure) are logged instead of silently swallowed
  - Wrap executeBuildifier in try/catch in checkBuildifierIsAvailable to
    prevent process errors from propagating uncaught to the void call site
  - Thread the validated buildifierPath through to BuildifierDiagnosticsManager
    and BuildifierFormatProvider to eliminate the TOCTOU gap between the
    availability check and runtime path resolution
  - Remove misleading async keyword from sync-only enable() in CodeLensFeature
    and WorkspaceTreeFeature; use explicit Promise.resolve() instead
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants