-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Enhance dbt-power-user Side Panel to Show Model Info for Non-SQL Files #1475
base: master
Are you sure you want to change the base?
Changes from 2 commits
0e8750f
1e8243e
adc62fc
5984671
148516a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { unmanaged } from "inversify"; | ||
import { provide } from "inversify-binding-decorators"; | ||
import * as path from "path"; | ||
|
||
import { | ||
Command, | ||
Disposable, | ||
|
@@ -29,7 +30,7 @@ import { | |
ManifestCacheChangedEvent, | ||
ManifestCacheProjectAddedEvent, | ||
} from "../manifest/event/manifestCacheChangedEvent"; | ||
import { provideSingleton } from "../utils"; | ||
import { getModelNameInActiveEditor, provideSingleton } from "../utils"; | ||
|
||
@provide(ModelTreeviewProvider) | ||
abstract class ModelTreeviewProvider | ||
|
@@ -54,6 +55,9 @@ abstract class ModelTreeviewProvider | |
this.dbtProjectContainer.onManifestChanged((event) => | ||
this.onManifestCacheChanged(event), | ||
), | ||
window.onDidChangeTextEditorSelection(() => { | ||
this._onDidChangeTreeData.fire(); | ||
}), | ||
); | ||
} | ||
|
||
|
@@ -104,15 +108,28 @@ abstract class ModelTreeviewProvider | |
if (element) { | ||
return Promise.resolve(this.getTreeItems(element.key, event)); | ||
} | ||
const fileName = path.basename( | ||
window.activeTextEditor!.document.fileName, | ||
".sql", | ||
|
||
const model_by_file_content = event.nodeMetaMap.lookupByBaseName( | ||
getModelNameInActiveEditor(), | ||
); | ||
const model = event.nodeMetaMap.lookupByBaseName(fileName); | ||
if (!model) { | ||
return Promise.resolve([]); | ||
|
||
if (model_by_file_content) { | ||
return Promise.resolve( | ||
this.getTreeItems(model_by_file_content.uniqueId, event), | ||
); | ||
} | ||
return Promise.resolve(this.getTreeItems(model.uniqueId, event)); | ||
|
||
const fileName = path.parse( | ||
window.activeTextEditor!.document.fileName, | ||
).name; | ||
const model_by_file_name = event.nodeMetaMap.lookupByBaseName(fileName); | ||
if (model_by_file_name) { | ||
return Promise.resolve( | ||
this.getTreeItems(model_by_file_name.uniqueId, event), | ||
); | ||
} | ||
|
||
return Promise.resolve([]); | ||
} | ||
|
||
private getNodeTreeItem(node: Node): NodeTreeItem { | ||
|
@@ -180,6 +197,9 @@ class DocumentationTreeviewProvider implements TreeDataProvider<DocTreeItem> { | |
this.dbtProjectContainer.onManifestChanged((event) => | ||
this.onManifestCacheChanged(event), | ||
), | ||
window.onDidChangeTextEditorSelection(() => { | ||
this._onDidChangeTreeData.fire(); | ||
}), | ||
); | ||
} | ||
|
||
|
@@ -222,14 +242,21 @@ class DocumentationTreeviewProvider implements TreeDataProvider<DocTreeItem> { | |
const { nodeMetaMap } = event; | ||
|
||
if (!element) { | ||
const modelName = path.basename( | ||
const fileName = path.parse( | ||
window.activeTextEditor!.document.fileName, | ||
".sql", | ||
).name; | ||
const currentNodeByFileName = | ||
event.nodeMetaMap.lookupByBaseName(fileName); | ||
const currentNodeByFileContent = event.nodeMetaMap.lookupByBaseName( | ||
getModelNameInActiveEditor(), | ||
); | ||
const currentNode = nodeMetaMap.lookupByBaseName(modelName); | ||
|
||
const currentNode = currentNodeByFileContent || currentNodeByFileName; | ||
if (currentNode === undefined) { | ||
return Promise.resolve([]); | ||
} | ||
const modelName = currentNode.name; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Align implementation with ModelTreeviewProvider and add validation There are two concerns with the current implementation:
Consider this improvement: - const currentNodeByFileName =
- event.nodeMetaMap.lookupByBaseName(fileName);
- const currentNodeByFileContent = event.nodeMetaMap.lookupByBaseName(
- getModelNameInActiveEditor(),
- );
-
- const currentNode = currentNodeByFileContent || currentNodeByFileName;
+ // Try content-based lookup first
+ const currentNodeByFileContent = event.nodeMetaMap.lookupByBaseName(
+ getModelNameInActiveEditor().catch(error => {
+ console.warn('Failed to parse editor content:', error);
+ return undefined;
+ })
+ );
+
+ // Fall back to filename-based lookup
+ const currentNode = currentNodeByFileContent ??
+ event.nodeMetaMap.lookupByBaseName(fileName);
if (currentNode === undefined) {
return Promise.resolve([]);
}
- const modelName = currentNode.name;
+ const modelName = currentNode?.name;
|
||
const children = []; | ||
|
||
if (Object.keys(currentNode.columns).length !== 0) { | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -8,9 +8,10 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TextDocument, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uri, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
workspace, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from "vscode"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { readFileSync } from "fs"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { parse } from "yaml"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { parse, parseDocument } from "yaml"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TestMetadataAcceptedValues, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TestMetadataRelationships, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -359,3 +360,40 @@ export const getStringSizeInMb = (str: string): number => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const sizeInMB = sizeInBytes / (1024 * 1024); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return sizeInMB; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export function getModelNameInActiveEditor(): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.activeTextEditor === undefined || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
window.activeTextEditor.document.languageId !== "yaml" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const parsedYaml = parseDocument(window.activeTextEditor.document.getText()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (parsedYaml.contents === null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const cursorPosition = window.activeTextEditor.selection.active; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const offset = window.activeTextEditor.document.offsetAt(cursorPosition); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// parseDocument returns Pair of Key-Value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// So, we need to find the node with key "models", and extract items of it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const models = (parsedYaml.contents as any).items.find( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(y: any) => y.key.value === "models", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
).value.items; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Find a model at the current position | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (const model of models) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// each element of models is a Pair of Key-Value, and Value is Scalar Type. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// So, we need to find the node with key "name", and extract value of it by toString | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const name = model.items | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.find((x: any) => x.key.value === "name") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.value.toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (model.range[0] < offset && offset < model.range[1]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return name; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling and type safety improvements. The current implementation has several potential points of failure that should be handled more gracefully:
Consider applying these improvements: export function getModelNameInActiveEditor(): string {
if (
window.activeTextEditor === undefined ||
window.activeTextEditor.document.languageId !== "yaml"
) {
return "";
}
- const parsedYaml = parseDocument(window.activeTextEditor.document.getText());
- if (parsedYaml.contents === null) {
- return "";
- }
+ try {
+ const parsedYaml = parseDocument(window.activeTextEditor.document.getText());
+ if (parsedYaml.contents === null) {
+ return "";
+ }
+ const cursorPosition = window.activeTextEditor.selection.active;
+ const offset = window.activeTextEditor.document.offsetAt(cursorPosition);
+
+ const contents = parsedYaml.contents as { items?: Array<any> };
+ if (!contents.items) {
+ return "";
+ }
+
+ const modelsNode = contents.items.find(
+ (item) => item?.key?.value === "models"
+ );
+ if (!modelsNode?.value?.items) {
+ return "";
+ }
+
+ // Find a model at the current position
+ for (const model of modelsNode.value.items) {
+ if (!model?.items) continue;
+
+ const nameNode = model.items.find(
+ (item) => item?.key?.value === "name"
+ );
+ if (!nameNode?.value) continue;
+
+ if (model.range?.[0] < offset && offset < model.range?.[1]) {
+ return nameNode.value.toString();
+ }
+ }
+ } catch (error) {
+ console.error("Error parsing YAML document:", error);
+ }
+ return "";
} 📝 Committable suggestion
Suggested change
💡 Codebase verification Based on the search results, I can now provide a final response: The YAML structure assumption in The function assumes all YAML files will have a specific structure with
🔗 Analysis chainVerify YAML structure assumptions across the codebase. Let's verify that all dbt YAML files in the project follow the expected structure. Let me gather more information about the YAML files in the codebase to better understand their structure and usage. Let me try one more search to specifically understand how the YAML parsing is used in the codebase. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Check for YAML files that might not follow the expected structure
# Expected structure: Should have 'models' key with array of objects containing 'name' field
# Find all YAML files
echo "Checking YAML files structure..."
fd -e yml -e yaml --exec sh -c '
echo "Checking: {}"
if ! yq eval ".models" {} >/dev/null 2>&1; then
echo "Warning: {} - missing or invalid models key"
elif ! yq eval ".models[].name" {} >/dev/null 2>&1; then
echo "Warning: {} - models missing name field"
fi
'
Length of output: 430 Script: #!/bin/bash
# Let's examine the content of YAML files to understand their structure
echo "=== Searching for YAML files ==="
fd -e yml -e yaml -x cat {}
echo -e "\n=== Searching for YAML file usage in code ==="
rg -g '*.{ts,js}' 'parseDocument.*\.ya?ml' -A 2 -B 2
Length of output: 1734 Script: #!/bin/bash
# Search for parseDocument usage and YAML handling
echo "=== Searching for parseDocument usage ==="
rg "parseDocument" -A 5 -B 5
echo -e "\n=== Searching for YAML-related code ==="
rg "languageId.*yaml" -A 5 -B 5
Length of output: 3542 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract shared model lookup logic to reduce code duplication
The model lookup logic is duplicated between
ModelTreeviewProvider
andDocumentationTreeviewProvider
. Consider extracting it into a shared utility function.Create a new utility function:
Then use it in both providers: