codeant-ai-for-open-source[bot] commented on code in PR #37642:
URL: https://github.com/apache/superset/pull/37642#discussion_r2760369166


##########
superset-frontend/packages/superset-core/src/api/sqlLab.ts:
##########
@@ -444,3 +448,193 @@ export declare const onDidCloseTab: Event<Tab>;
  * ```
  */
 export declare const onDidChangeActiveTab: Event<Tab>;
+
+/**
+ * Event fired when a new tab is created in SQL Lab.
+ * Provides the newly created tab object as the event payload.
+ *
+ * @example
+ * ```typescript
+ * onDidCreateTab.event((tab) => {
+ *   console.log('New tab created:', tab.title);
+ *   // Initialize extension state for new tab
+ * });
+ * ```
+ */
+export declare const onDidCreateTab: Event<Tab>;
+
+/**
+ * Tab/Editor Management APIs
+ *
+ * These APIs allow extensions to create, close, and manage SQL Lab tabs.
+ */
+
+/**
+ * Options for creating a new SQL Lab tab.
+ */
+export interface CreateTabOptions {
+  /**
+   * Initial SQL content for the editor.
+   */
+  sql?: string;
+
+  /**
+   * Display title for the tab.
+   * If not provided, defaults to "Untitled Query N".
+   */
+  title?: string;
+
+  /**
+   * Database ID to connect to.
+   * If not provided, inherits from the active tab or uses default.
+   */
+  databaseId?: number;
+
+  /**
+   * Catalog name (for multi-catalog databases like Trino).
+   */
+  catalog?: string | null;
+
+  /**
+   * Schema name for the query context.
+   */
+  schema?: string;
+}

Review Comment:
   **Suggestion:** `CreateTabOptions.schema` is typed as `string` while 
`Tab.schema` and `setSchema` allow `string | null`, so you cannot pass `null` 
when creating a tab even though other parts of the API treat schema as 
nullable, leading to inconsistent typing and potential runtime handling 
differences. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ createTab callers cannot pass null schema.
   - ⚠️ Inconsistent API nullability semantics.
   ```
   </details>
   
   ```suggestion
      schema?: string | null;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open `superset-frontend/packages/superset-core/src/api/sqlLab.ts` and 
locate
   `CreateTabOptions` (starts at line ~475 in the PR hunk). The `schema` option 
is declared
   as `schema?: string;` (line 501).
   
   2. Inspect the `Tab` interface earlier in the same file: `schema: string | 
null;`
   (Tab.schema defined at ~line 87) and the function `setSchema(schema: string 
| null):
   Promise<void>;` (declared around line 640). The rest of the API treats 
schema as nullable.
   
   3. In a TypeScript consumer, call `createTab({ databaseId: 1, schema: null 
})`. The
   compiler will error because `null` is not assignable to parameter type 
`string |
   undefined` for `schema?: string`.
   
   4. The mismatch prevents callers from explicitly passing `null` when they 
intend to
   clear/explicitly set an empty schema; changing `schema?: string | null` in
   `CreateTabOptions` aligns types.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/packages/superset-core/src/api/sqlLab.ts
   **Line:** 502:502
   **Comment:**
        *Type Error: `CreateTabOptions.schema` is typed as `string` while 
`Tab.schema` and `setSchema` allow `string | null`, so you cannot pass `null` 
when creating a tab even though other parts of the API treat schema as 
nullable, leading to inconsistent typing and potential runtime handling 
differences.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/packages/superset-core/src/api/sqlLab.ts:
##########
@@ -327,8 +331,8 @@ export declare const onDidChangeTabTitle: Event<string>;
  * @example
  * ```typescript
  * onDidQueryRun.event((query) => {
- *   console.log('Query started on database:', query.tab.editor.databaseId);
- *   console.log('Query content:', query.tab.editor.content);
+ *   console.log('Query started on database:', query.tab.databaseId);
+ *   console.log('Query SQL:', query.tab.editor.getValue());

Review Comment:
   **Suggestion:** The `onDidQueryRun` JSDoc example accesses 
`query.tab.editor.getValue()`, but `Tab` no longer exposes an `editor` property 
and now requires using the async `getEditor()` method, so this example will not 
compile and misrepresents the public API. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Event-handler examples won't compile for extensions.
   - ⚠️ Misleading docs for query run listeners.
   ```
   </details>
   
   ```suggestion
    *   query.tab.getEditor().then(editor => {
    *     console.log('Query SQL:', editor.getValue());
    *   });
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open `superset-frontend/packages/superset-core/src/api/sqlLab.ts` and 
find the
   `onDidQueryRun` JSDoc example (example snippet shown at lines 333-336 in the 
PR hunk). The
   example references `query.tab.editor.getValue()`.
   
   2. Note the event declaration for `onDidQueryRun` is `export declare const 
onDidQueryRun:
   Event<QueryContext>;` (declaration appears in the same file, nearby in the 
docs at ~line
   345), and `QueryContext.tab` has type `Tab` whose `editor` property was 
removed in favor
   of `getEditor(): Promise<Editor>` (Tab.getEditor defined at ~line 105).
   
   3. Copy the example into an extension and attempt to compile/use it. 
TypeScript will
   report an error because `query.tab.editor` does not exist on `Tab`, 
preventing consumers
   from compiling code that follows the example.
   
   4. The observed failure is a documentation/type mismatch — the example 
should demonstrate
   `query.tab.getEditor()` instead of the removed `editor` property to reflect 
the actual API
   surface.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/packages/superset-core/src/api/sqlLab.ts
   **Line:** 335:335
   **Comment:**
        *Possible Bug: The `onDidQueryRun` JSDoc example accesses 
`query.tab.editor.getValue()`, but `Tab` no longer exposes an `editor` property 
and now requires using the async `getEditor()` method, so this example will not 
compile and misrepresents the public API.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/core/sqlLab/index.ts:
##########
@@ -340,10 +431,10 @@ const onDidCloseTab: typeof sqlLabApi.onDidCloseTab = (
   thisArgs?: any,
 ): Disposable =>
   createActionListener(
-    predicate(REMOVE_QUERY_EDITOR),
+    globalPredicate(REMOVE_QUERY_EDITOR),
     listener,
     (action: { type: string; queryEditor: { id: string } }) =>
-      getTab(action.queryEditor.id)!,
+      getTab(action.queryEditor.id),
     thisArgs,

Review Comment:
   **Suggestion:** `onDidCloseTab` derives the `Tab` from the Redux state after 
the `REMOVE_QUERY_EDITOR` action has been reduced, so the tab has already been 
removed and `getTab` returns `undefined`, causing listeners expecting a valid 
`Tab` to receive `undefined` and potentially crash when using it. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ onDidCloseTab listeners receive undefined Tab.
   - ⚠️ Listeners calling tab methods will throw.
   - ⚠️ Close-tab workflows and integrations affected.
   ```
   </details>
   
   ```suggestion
         (action: { type: string; queryEditor: QueryEditor }) =>
           makeTab(
             action.queryEditor.id!,
             action.queryEditor.name ?? '',
             action.queryEditor.dbId ?? 0,
             action.queryEditor.catalog,
             action.queryEditor.schema ?? undefined,
           ),
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Register a close-tab listener using the exported API: 
`sqlLab.onDidCloseTab(listener)`
   (listener registration code lives at
   `superset-frontend/src/core/sqlLab/index.ts:431-439`).
   
   2. Trigger a tab close via the public API `sqlLab.closeTab(tabId)` 
(implementation
   dispatches `REMOVE_QUERY_EDITOR` at 
`superset-frontend/src/core/sqlLab/index.ts:573-578`).
   
   3. The `REMOVE_QUERY_EDITOR` action is dispatched
   (`superset-frontend/src/core/sqlLab/index.ts:576`), reducers remove the 
query editor from
   state.
   
   4. The action listener's mapper calls `getTab(action.queryEditor.id)` (line
   `superset-frontend/src/core/sqlLab/index.ts:437`) — because the reducer 
already removed
   the editor, `getTab` returns `undefined`, so the registered `listener` 
receives
   `undefined` instead of a valid `Tab`; reproduce by registering a listener 
that
   dereferences the tab (e.g., calls `tab.getEditor()`), then calling 
`sqlLab.closeTab(id)`
   and observing a runtime error.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/core/sqlLab/index.ts
   **Line:** 438:438
   **Comment:**
        *Logic Error: `onDidCloseTab` derives the `Tab` from the Redux state 
after the `REMOVE_QUERY_EDITOR` action has been reduced, so the tab has already 
been removed and `getTab` returns `undefined`, causing listeners expecting a 
valid `Tab` to receive `undefined` and potentially crash when using it.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/packages/superset-core/src/api/sqlLab.ts:
##########
@@ -262,7 +262,11 @@ export declare const getActivePanel: () => Panel;
  * const tab = getCurrentTab();
  * if (tab) {
  *   console.log(`Active tab: ${tab.title}`);
- *   console.log(`Database ID: ${tab.editor.databaseId}`);
+ *   console.log(`Database ID: ${tab.databaseId}, Schema: ${tab.schema}`);
+ *
+ *   // Direct editor manipulation
+ *   tab.editor.setValue("SELECT * FROM users");
+ *   tab.editor.focus();

Review Comment:
   **Suggestion:** The JSDoc example for `getCurrentTab` still uses a 
synchronous `tab.editor` property, which no longer exists on `Tab` and will 
both fail type-checking and mislead consumers; it should demonstrate using the 
async `getEditor()` API instead. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Extension examples cause TypeScript compile errors.
   - ⚠️ Consumers misled by invalid API example.
   ```
   </details>
   
   ```suggestion
    *   tab.getEditor().then(editor => {
    *     editor.setValue("SELECT * FROM users");
    *     editor.focus();
    *   });
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open the declaration file 
`superset-frontend/packages/superset-core/src/api/sqlLab.ts`
   and locate the `getCurrentTab` example in the JSDoc (lines shown at 265-269 
in the PR
   hunk). The example shows `tab.editor.setValue(...)` and `tab.editor.focus()` 
while the
   `Tab` interface no longer exposes `editor`.
   
   2. In an extension/consumer TypeScript project, copy the example lines into 
a module and
   call `const tab = getCurrentTab(); if (tab) { tab.editor.setValue("..."); 
}`. The consumer
   imports types from the package that include `Tab` as declared in the same 
file
   (`getEditor(): Promise<Editor>` at line ~105 in the Tab interface).
   
   3. Run `tsc` (or let the IDE typechecker run). The TypeScript compiler will 
error because
   `Tab` does not have an `editor` property (the correct API is `getEditor()`), 
producing a
   compile-time type error at the site where `tab.editor` is referenced.
   
   4. Observe the incorrect example causes immediate developer friction: the 
code in
   `sqlLab.ts` (lines 265-269) misleads consumers and results in compile-time 
errors. This is
   a documentation/type mismatch issue, not a runtime crash.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/packages/superset-core/src/api/sqlLab.ts
   **Line:** 268:269
   **Comment:**
        *Possible Bug: The JSDoc example for `getCurrentTab` still uses a 
synchronous `tab.editor` property, which no longer exists on `Tab` and will 
both fail type-checking and mislead consumers; it should demonstrate using the 
async `getEditor()` API instead.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/core/utils.ts:
##########
@@ -24,7 +24,7 @@ import { AnyListenerPredicate } from '@reduxjs/toolkit';
 export function createActionListener<V, S>(
   predicate: AnyListenerPredicate<S>,
   listener: (v: V) => void,
-  valueParser: (action: AnyAction, state: RootState) => V,
+  valueParser: (action: AnyAction, state: RootState) => V | null | undefined,

Review Comment:
   **Suggestion:** The helper is generic over the state type `S` for the 
predicate but hardcodes `RootState` in the `valueParser` signature, creating 
inconsistent typing for the state parameter; this forces callers to reconcile 
mismatched types and can lead to unsafe casts or incorrect assumptions about 
the state shape. Aligning `valueParser` to use the same generic state type `S` 
keeps the contract consistent and type-safe. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Type errors when registering listeners (src/core/utils.ts).
   - ⚠️ Prevents typed predicates using non-RootState.
   - ⚠️ Affects modules calling createActionListener.
   ```
   </details>
   
   ```suggestion
     valueParser: (action: AnyAction, state: S) => V | null | undefined,
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Inspect the helper declaration at 
`superset-frontend/src/core/utils.ts:24-29` (function
   `createActionListener`).
   
   2. Create/modify a consumer file that imports the helper and supplies a 
predicate
   specialized to a narrower state type S (for example a slice type). Example 
consumer (new
   file) `superset-frontend/src/__tests__/exampleListener.ts:1-8`:
   
      - import { createActionListener } from 'src/core/utils';
   
      - type SliceState = { counter: number };
   
      - createActionListener<SliceState>(
   
          (action, state) => /* predicate using SliceState */,
   
          (value) => {},
   
          (action, state: SliceState) => null,
   
        );
   
   3. Run the TypeScript compiler (e.g. `yarn build` / `yarn tsc`). The 
compiler will
   reference the helper signature in `src/core/utils.ts:24-29` and will report 
a type
   incompatibility because `valueParser` is declared to receive `RootState` 
while the
   consumer expects `state` of type `SliceState`. Typical error: "Type 
'(action, state:
   SliceState) => ...' is not assignable to parameter of type '(action, state: 
RootState) =>
   ...'".
   
   4. Observe the compile-time failure preventing the consumer from registering 
a
   strongly-typed listener. Note: a repository-wide search shows the helper is 
defined at
   `superset-frontend/src/core/utils.ts:24-29` and there are likely callers 
that rely on
   typed predicates; if callers always use `RootState` this error won't appear 
until a
   consumer uses a non-RootState `S`.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/core/utils.ts
   **Line:** 27:27
   **Comment:**
        *Type Error: The helper is generic over the state type `S` for the 
predicate but hardcodes `RootState` in the `valueParser` signature, creating 
inconsistent typing for the state parameter; this forces callers to reconcile 
mismatched types and can lead to unsafe casts or incorrect assumptions about 
the state shape. Aligning `valueParser` to use the same generic state type `S` 
keeps the contract consistent and type-safe.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to