ifc-language-server/client/out/ifcTreeProvider.js
Ryan Schultz 1296117135 feat: Add IFC Entity References panel with interactive updates
New Features:
- New sidebar panel 'IFC Entity References' shows all locations where an entity is used
- Ctrl+Click on any entity now updates BOTH hierarchy and references panels
- Clicking items in hierarchy tree updates references panel (but keeps hierarchy view)
- Command 'IFC: Find Entity References' to manually trigger reference search
- Clickable reference items jump directly to that line in the file
- Shows line numbers and reference icons for clarity

Usage:
- Ctrl+Click #13 → see what #13 depends on (hierarchy) AND where #13 is used (references)
- Click #4 in hierarchy tree → jump to #4 and see where #4 is used
- Both panels work together to give complete entity relationship view

Makes it easy to understand both dependencies (what it uses) and usage (what uses it).
2025-12-07 12:02:30 -06:00

124 lines
No EOL
4.3 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IfcEntityTreeProvider = void 0;
const vscode = require("vscode");
class IfcEntityTreeProvider {
_onDidChangeTreeData = new vscode.EventEmitter();
onDidChangeTreeData = this._onDidChangeTreeData.event;
currentEntity = null;
documentUri = null;
allEntities = new Map();
refresh() {
this._onDidChangeTreeData.fire();
}
async updateForEntity(entityId, document) {
this.documentUri = document.uri;
// Parse all entities from document
this.allEntities = this.parseEntities(document);
// Build hierarchy for the selected entity
this.currentEntity = this.buildHierarchy(entityId, this.allEntities);
this.refresh();
}
getTreeItem(element) {
return element;
}
getChildren(element) {
if (!this.currentEntity) {
return Promise.resolve([]);
}
if (!element) {
// Root level - show the current entity
return Promise.resolve([this.createTreeItem(this.currentEntity)]);
}
// Show children of this entity
const children = element.entityNode.children.map(child => this.createTreeItem(child));
return Promise.resolve(children);
}
createTreeItem(node) {
const hasChildren = node.children.length > 0;
const treeItem = new EntityTreeItem(node, hasChildren ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.None);
// Make it clickable - jump to line AND update references panel
if (this.documentUri) {
treeItem.command = {
command: 'ifc.updateReferencesFromTree',
title: 'Go to Entity and Show References',
arguments: [node.id, this.documentUri, node.line, node.fullText.length]
};
}
return treeItem;
}
parseEntities(document) {
const entities = new Map();
const text = document.getText();
const lines = text.split('\n');
const entityPattern = /^#(\d+)=(\w+)\(/;
lines.forEach((line, index) => {
const match = entityPattern.exec(line.trim());
if (match) {
const id = parseInt(match[1]);
const type = match[2];
entities.set(id, {
id,
type,
line: index,
fullText: line.trim(),
children: []
});
}
});
return entities;
}
extractEntityReferences(text) {
const references = [];
const pattern = /#(\d+)/g;
let match;
while ((match = pattern.exec(text)) !== null) {
const refId = parseInt(match[1]);
if (!references.includes(refId)) {
references.push(refId);
}
}
return references;
}
buildHierarchy(entityId, entities, visited = new Set()) {
if (visited.has(entityId)) {
return null; // Prevent circular references
}
visited.add(entityId);
const entity = entities.get(entityId);
if (!entity) {
return null;
}
// Create a copy to avoid modifying the original
const node = {
...entity,
children: []
};
// Get references and build children
const references = this.extractEntityReferences(entity.fullText);
for (const refId of references) {
if (refId !== entityId) {
const childNode = this.buildHierarchy(refId, entities, new Set(visited));
if (childNode) {
node.children.push(childNode);
}
}
}
return node;
}
}
exports.IfcEntityTreeProvider = IfcEntityTreeProvider;
class EntityTreeItem extends vscode.TreeItem {
entityNode;
collapsibleState;
constructor(entityNode, collapsibleState) {
// Show the full entity line as the label
super(entityNode.fullText, collapsibleState);
this.entityNode = entityNode;
this.collapsibleState = collapsibleState;
// Keep the full text as tooltip
this.tooltip = entityNode.fullText;
// Don't set description - we don't want the type repeated
}
}
//# sourceMappingURL=ifcTreeProvider.js.map