Skip to content

fix: refactor autocomplete system for reliability#384

Merged
datlechin merged 2 commits intomainfrom
fix/autocomplete-refactor
Mar 20, 2026
Merged

fix: refactor autocomplete system for reliability#384
datlechin merged 2 commits intomainfrom
fix/autocomplete-refactor

Conversation

@datlechin
Copy link
Collaborator

@datlechin datlechin commented Mar 20, 2026

Summary

  • Fix Caps Lock and Function key modifier flags breaking Ctrl+Space and Escape shortcuts (root cause of user-reported autocomplete not triggering)
  • Replace fragile weak var delegate references on SourceEditor struct with strong vars (TextViewController already keeps proper weak refs)
  • Cancel in-flight completion tasks instead of silently blocking new typing triggers
  • Replace NSWindow with NSPanel subclass (SuggestionPanel) to fix canBecomeKeyWindow warnings
  • Add isManualTrigger flag so Ctrl+Space always shows completions even with empty prefix/empty editor
  • Wire up previously dead updateSchemaProvider code on connection change
  • Add schema load retry with 30s cooldown for failed initial loads
  • Add diagnostic logging (os.Logger) at key failure points in the completion pipeline

Test plan

  • With Caps Lock ON: verify Ctrl+Space and Escape trigger autocomplete
  • Empty editor: Ctrl+Space shows SQL statement starters (SELECT, INSERT, etc.)
  • Type SELECT * FROM u — autocomplete appears at u
  • Type SELECT rapidly — completions appear after last keystroke (no dropped triggers)
  • Console.app: no more canBecomeKeyWindow warnings
  • Disconnect and reconnect: autocomplete still works (schema provider update)
  • Cmd+/ and Cmd+F still work (no regression in other shortcuts)

Summary by CodeRabbit

  • New Features

    • Manual trigger support for code suggestions to show all completions.
    • Schema retry mechanism for auto-completion to ensure data freshness.
    • Connection-aware schema updates when editor connection changes.
  • Bug Fixes

    • Improved completion filtering for manual vs automatic triggers.
    • Modifier-key handling corrected for event processing.
    • Completion UI adjusted to avoid stealing window focus.
    • Added cooldown protection for schema reloads.
  • Chores

    • Enhanced logging for completion flow troubleshooting.
    • Delegate reference handling updated for more reliable retention.

- Strip .capsLock and .function from modifier flags so Escape/Ctrl+Space work on all keyboards
- Remove weak var on SourceEditor struct delegates to prevent nil reference issues
- Cancel in-flight completion tasks instead of blocking new triggers
- Replace NSWindow with NSPanel subclass to fix canBecomeKeyWindow warnings
- Add isManualTrigger flag so Ctrl+Space shows completions even with empty prefix
- Wire up updateSchemaProvider on connection change (was dead code)
- Add schema load retry with 30s cooldown for failed initial loads
- Add diagnostic logging at key completion pipeline failure points
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds manual vs automatic completion trigger signaling, logging across suggestion flow, switches suggestion window from NSWindow to NSPanel, changes two delegates to strong references, and implements conditional schema-retry with cooldown for SQL completions.

Changes

Cohort / File(s) Summary
Code Suggestion Protocol Updates
LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/CodeSuggestionDelegate.swift
Protocol method signature updated to include isManualTrigger: Bool; protocol extension adds overloaded default implementations for backward compatibility.
Suggestion UI & Window Management
.../CodeSuggestion/Window/SuggestionController.swift, .../CodeSuggestion/Window/SuggestionController+Window.swift, .../CodeSuggestion/Model/SuggestionViewModel.swift
Threaded isManualTrigger through controller → model; created SuggestionPanel: NSPanel and switched factory to return NSPanel; added logging and additional early-return checks, and modified task cancellation behavior.
TextView & Trigger Handling
LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Controller/TextViewController+Lifecycle.swift, LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionTriggerCharacterModel.swift
Keyboard event modifier filtering changed (exclude capsLock/function); handleShowCompletions now calls showCompletions with isManualTrigger: true; added os logging and debug messages for early-return cases.
SourceEditor Delegate Retention
LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditor/SourceEditor.swift
Changed completionDelegate and jumpToDefinitionDelegate from weak to strong references.
SQL Completion Schema Retry
TablePro/Core/Autocomplete/CompletionEngine.swift, TablePro/Core/Autocomplete/SQLCompletionProvider.swift, TablePro/Core/Autocomplete/SQLSchemaProvider.swift
Added async retry API surface (retrySchemaIfNeeded / retryLoadSchemaIfNeeded) with cooldown and conditional retry logic; engine/provider methods added to trigger schema reload attempts.
SQL Completion Adapter & Editor Integration
TablePro/Views/Editor/SQLCompletionAdapter.swift, TablePro/Views/Editor/SQLEditorView.swift
Adapter method gains isManualTrigger param and skips empty-prefix suppression for manual triggers; calls schema retry before computing completions and adds logging for missing engine; editor view adds onChange(of: connectionId) to refresh schema provider and favorites observer.

Sequence Diagram

sequenceDiagram
    participant User
    participant TextView as TextViewController
    participant SuggestCtrler as SuggestionController
    participant SuggestModel as SuggestionViewModel
    participant Adapter as SQLCompletionAdapter
    participant Engine as CompletionEngine
    participant SchemaProvider as SQLSchemaProvider

    rect rgba(0, 150, 200, 0.5)
    note over User,SchemaProvider: Manual Trigger Flow
    User->>TextView: Press completion shortcut
    TextView->>SuggestCtrler: showCompletions(isManualTrigger: true)
    SuggestCtrler->>SuggestModel: showCompletions(..., isManualTrigger: true)
    SuggestModel->>Adapter: completionSuggestionsRequested(..., isManualTrigger: true)
    Adapter->>Engine: retrySchemaIfNeeded()
    Engine->>SchemaProvider: retryLoadSchemaIfNeeded()
    alt Schema retry successful or not needed
        SchemaProvider-->>Engine: ✓
        Engine-->>Adapter: ✓
    end
    Adapter->>Engine: getCompletions()
    Engine-->>Adapter: Completion items
    Adapter-->>SuggestModel: Return items (no empty-prefix suppression)
    SuggestModel->>SuggestModel: Show completion window
    end

    rect rgba(100, 150, 50, 0.5)
    note over User,SchemaProvider: Automatic Trigger Flow
    User->>TextView: Type completion character
    TextView->>SuggestCtrler: showCompletions(isManualTrigger: false)
    SuggestCtrler->>SuggestModel: showCompletions(..., isManualTrigger: false)
    SuggestModel->>Adapter: completionSuggestionsRequested(..., isManualTrigger: false)
    Adapter->>Engine: retrySchemaIfNeeded()
    Engine->>SchemaProvider: retryLoadSchemaIfNeeded()
    SchemaProvider-->>Engine: ✓
    Engine-->>Adapter: ✓
    Adapter->>Engine: getCompletions()
    Engine-->>Adapter: Completion items
    Adapter->>Adapter: Filter: suppress empty-prefix items
    Adapter-->>SuggestModel: Return filtered items
    SuggestModel->>SuggestModel: Show completion window
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through code and logs tonight,
Manual taps make suggestions bright.
Panels that don't steal the key,
Schemas retry, then set us free—
Hooray! Completions take flight ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective: a refactor to improve autocomplete system reliability through multiple targeted fixes (modifier key handling, delegate references, task cancellation, window management, manual trigger flag, schema retry, and logging).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/autocomplete-refactor
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionViewModel.swift (1)

13-13: Consider using a package-appropriate logger subsystem.

This file is in the CodeEditSourceEditor package, but the logger uses the "com.TablePro" subsystem. If this package is intended to be reusable or shared, a package-specific subsystem (e.g., "com.CodeEditSourceEditor") would be more appropriate for filtering and identification.

However, if this package is exclusively used within TablePro and you want unified log filtering, the current approach is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionViewModel.swift`
at line 13, The logger subsystem string in the static logger declaration uses
"com.TablePro" which is package-mismatched; update the Logger initialization in
SuggestionViewModel (the private static let logger) to use a package-appropriate
subsystem such as "com.CodeEditSourceEditor" (or another package-specific
identifier) so logs are correctly categorized for this package while keeping the
category "SuggestionVM" unchanged.
LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController+Window.swift (1)

11-14: Add explicit access control to SuggestionPanel.

Per coding guidelines, access control should be explicitly specified on types. Since this panel is only used internally by SuggestionController, it should be marked private or internal.

♻️ Suggested fix
-final class SuggestionPanel: NSPanel {
+private final class SuggestionPanel: NSPanel {
     override var canBecomeKey: Bool { false }
     override var canBecomeMain: Bool { false }
 }

As per coding guidelines: "Always specify access control explicitly (private, internal, public) on extensions and types."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController`+Window.swift
around lines 11 - 14, The SuggestionPanel type lacks explicit access control;
change its declaration from "final class SuggestionPanel" to an explicit access
level (e.g., "private final class SuggestionPanel") since it is only used
internally by SuggestionController, and update any references in
SuggestionController to match that access level so the compiler and style
guidelines are satisfied.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@TablePro/Views/Editor/SQLEditorView.swift`:
- Around line 82-86: The favorites binding remains tied to the old connection
because setupFavoritesObserver() captures connectionId once; when connectionId
changes (the same place where
completionAdapter.updateSchemaProvider(schemaProvider, databaseType:
databaseType) is called), tear down or re-register the favorites observer for
the new connectionId by calling the same logic as setupFavoritesObserver() (or
provide a teardown + setup sequence) so favorites suggestions are rebound to the
new connection; locate the connection change block (onChange of connectionId),
the setupFavoritesObserver() function, and the
completionAdapter.updateSchemaProvider(...) call and ensure you reinitialize the
favorites observer (or remove old observer) there when connectionId changes.

---

Nitpick comments:
In
`@LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionViewModel.swift`:
- Line 13: The logger subsystem string in the static logger declaration uses
"com.TablePro" which is package-mismatched; update the Logger initialization in
SuggestionViewModel (the private static let logger) to use a package-appropriate
subsystem such as "com.CodeEditSourceEditor" (or another package-specific
identifier) so logs are correctly categorized for this package while keeping the
category "SuggestionVM" unchanged.

In
`@LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController`+Window.swift:
- Around line 11-14: The SuggestionPanel type lacks explicit access control;
change its declaration from "final class SuggestionPanel" to an explicit access
level (e.g., "private final class SuggestionPanel") since it is only used
internally by SuggestionController, and update any references in
SuggestionController to match that access level so the compiler and style
guidelines are satisfied.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7f01c22e-7b52-4cb4-8e1c-ef1c4e439bea

📥 Commits

Reviewing files that changed from the base of the PR and between fe882ff and 74a8d86.

📒 Files selected for processing (12)
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/CodeSuggestionDelegate.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionTriggerCharacterModel.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Model/SuggestionViewModel.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController+Window.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/CodeSuggestion/Window/SuggestionController.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Controller/TextViewController+Lifecycle.swift
  • LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditor/SourceEditor.swift
  • TablePro/Core/Autocomplete/CompletionEngine.swift
  • TablePro/Core/Autocomplete/SQLCompletionProvider.swift
  • TablePro/Core/Autocomplete/SQLSchemaProvider.swift
  • TablePro/Views/Editor/SQLCompletionAdapter.swift
  • TablePro/Views/Editor/SQLEditorView.swift

- Add setupFavoritesObserver() on connectionId change to rebind favorites
- Add explicit access control to SuggestionPanel (internal)
- Use package-appropriate logger subsystem in CodeEditSourceEditor
@datlechin datlechin merged commit ae17f84 into main Mar 20, 2026
2 of 3 checks passed
@datlechin datlechin deleted the fix/autocomplete-refactor branch March 20, 2026 04:48
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.

1 participant