mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Enhance json outline example
This commit is contained in:
26
tree-view-sample/.vscode/launch.json
vendored
26
tree-view-sample/.vscode/launch.json
vendored
@ -7,10 +7,14 @@
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceRoot}"],
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": ["${workspaceRoot}/out/src/**/*.js"],
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/out/src/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm"
|
||||
},
|
||||
{
|
||||
@ -18,21 +22,27 @@
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}",
|
||||
"--extensionTestsPath=${workspaceRoot}/out/test"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": ["${workspaceRoot}/out/test/**/*.js"],
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/out/test/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach to Extension Host",
|
||||
"protocol": "legacy",
|
||||
"protocol": "inspector",
|
||||
"port": 5870,
|
||||
"sourceMaps": true,
|
||||
"restart": true,
|
||||
"outDir": "${workspaceRoot}/out/src"
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/out/src"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -55,10 +55,23 @@
|
||||
{
|
||||
"command": "openFtpResource",
|
||||
"title": "Open FTP Resource"
|
||||
},
|
||||
{
|
||||
"command": "jsonOutline.refresh",
|
||||
"title": "Refresh",
|
||||
"icon": {
|
||||
"light": "resources/light/refresh.svg",
|
||||
"dark": "resources/dark/refresh.svg"
|
||||
}
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"view/title": [
|
||||
{
|
||||
"command": "jsonOutline.refresh",
|
||||
"when": "view == jsonOutline",
|
||||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "nodeDependencies.refreshEntry",
|
||||
"when": "view == nodeDependencies",
|
||||
|
||||
@ -14,6 +14,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
const ftpExplorerProvider = new FtpTreeDataProvider();
|
||||
|
||||
vscode.window.registerTreeDataProvider('nodeDependencies', nodeDependenciesProvider);
|
||||
vscode.commands.registerCommand('jsonOutline.refresh', () => jsonOutlineProvider.refresh());
|
||||
vscode.window.registerTreeDataProvider('jsonOutline', jsonOutlineProvider);
|
||||
vscode.window.registerTreeDataProvider('ftpExplorer', ftpExplorerProvider);
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@ import * as vscode from 'vscode';
|
||||
import * as json from 'jsonc-parser';
|
||||
import * as path from 'path';
|
||||
|
||||
export class JsonOutlineProvider implements vscode.TreeDataProvider<json.Node> {
|
||||
export class JsonOutlineProvider implements vscode.TreeDataProvider<string> {
|
||||
|
||||
private _onDidChangeTreeData: vscode.EventEmitter<json.Node | null> = new vscode.EventEmitter<json.Node | null>();
|
||||
readonly onDidChangeTreeData: vscode.Event<json.Node | null> = this._onDidChangeTreeData.event;
|
||||
private _onDidChangeTreeData: vscode.EventEmitter<string | null> = new vscode.EventEmitter<string | null>();
|
||||
readonly onDidChangeTreeData: vscode.Event<string | null> = this._onDidChangeTreeData.event;
|
||||
|
||||
private tree: json.Node;
|
||||
private text: string;
|
||||
@ -13,20 +13,25 @@ export class JsonOutlineProvider implements vscode.TreeDataProvider<json.Node> {
|
||||
|
||||
constructor(private context: vscode.ExtensionContext) {
|
||||
vscode.window.onDidChangeActiveTextEditor(editor => {
|
||||
this.parseTree();
|
||||
this._onDidChangeTreeData.fire();
|
||||
this.refresh();
|
||||
});
|
||||
vscode.workspace.onDidChangeTextDocument(e => this.onDocumentChanged(e));
|
||||
this.parseTree();
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
this.parseTree();
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
private onDocumentChanged(changeEvent: vscode.TextDocumentChangeEvent): void {
|
||||
if (changeEvent.document.uri.toString() === this.editor.document.uri.toString()) {
|
||||
for (const change of changeEvent.contentChanges) {
|
||||
const location = json.getLocation(this.text, this.editor.document.offsetAt(change.range.start));
|
||||
const node = json.findNodeAtLocation(this.tree, location.path);
|
||||
const path = json.getLocation(this.text, this.editor.document.offsetAt(change.range.start)).path;
|
||||
path.pop();
|
||||
const node = path.length ? json.findNodeAtLocation(this.tree, path) : void 0;
|
||||
this.parseTree();
|
||||
this._onDidChangeTreeData.fire(node);
|
||||
this._onDidChangeTreeData.fire(node ? `${node.offset}` : void 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,38 +46,44 @@ export class JsonOutlineProvider implements vscode.TreeDataProvider<json.Node> {
|
||||
}
|
||||
}
|
||||
|
||||
getChildren(node?: json.Node): Thenable<json.Node[]> {
|
||||
if (node) {
|
||||
return Promise.resolve(this._getChildren(node));
|
||||
getChildren(offset?: string): Thenable<string[]> {
|
||||
if (offset) {
|
||||
const path = json.getLocation(this.text, parseInt(offset)).path
|
||||
const node = json.findNodeAtLocation(this.tree, path);
|
||||
return Promise.resolve(this.getChildrenOffsets(node));
|
||||
} else {
|
||||
return Promise.resolve(this.tree ? this.tree.children : []);
|
||||
return Promise.resolve(this.tree ? this.getChildrenOffsets(this.tree) : []);
|
||||
}
|
||||
}
|
||||
|
||||
private _getChildren(node: json.Node): json.Node[] {
|
||||
return node.parent.type === 'array' ? this.toArrayValueNode(node) : (node.type === 'array' ? node.children[0].children : node.children[1].children);
|
||||
}
|
||||
|
||||
private toArrayValueNode(node: json.Node): json.Node[] {
|
||||
if (node.type === 'array' || node.type === 'object') {
|
||||
return node.children;
|
||||
private getChildrenOffsets(node: json.Node): string[] {
|
||||
const offsets = [];
|
||||
for (const child of node.children) {
|
||||
const childPath = json.getLocation(this.text, child.offset).path
|
||||
const childNode = json.findNodeAtLocation(this.tree, childPath);
|
||||
if (childNode) {
|
||||
offsets.push(childNode.offset.toString());
|
||||
}
|
||||
}
|
||||
node['arrayValue'] = true;
|
||||
return [node];
|
||||
return offsets;
|
||||
}
|
||||
|
||||
getTreeItem(node: json.Node): vscode.TreeItem {
|
||||
let valueNode = node.parent.type === 'array' ? node : node.children[1];
|
||||
let hasChildren = (node.parent.type === 'array' && !node['arrayValue']) || valueNode.type === 'object' || valueNode.type === 'array';
|
||||
let treeItem: vscode.TreeItem = new vscode.TreeItem(this.getLabel(node), hasChildren ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None);
|
||||
treeItem.command = {
|
||||
command: 'extension.openJsonSelection',
|
||||
title: '',
|
||||
arguments: [new vscode.Range(this.editor.document.positionAt(node.offset), this.editor.document.positionAt(node.offset + node.length))]
|
||||
};
|
||||
treeItem.iconPath = this.getIcon(node);
|
||||
treeItem.contextValue = this.getNodeType(node);
|
||||
return treeItem;
|
||||
getTreeItem(offset: string): vscode.TreeItem {
|
||||
const path = json.getLocation(this.text, parseInt(offset)).path
|
||||
const valueNode = json.findNodeAtLocation(this.tree, path);
|
||||
if (valueNode) {
|
||||
let hasChildren = valueNode.type === 'object' || valueNode.type === 'array';
|
||||
let treeItem: vscode.TreeItem = new vscode.TreeItem(this.getLabel(valueNode), hasChildren ? valueNode.type === 'object' ? vscode.TreeItemCollapsibleState.Expanded : vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None);
|
||||
treeItem.command = {
|
||||
command: 'extension.openJsonSelection',
|
||||
title: '',
|
||||
arguments: [new vscode.Range(this.editor.document.positionAt(valueNode.offset), this.editor.document.positionAt(valueNode.offset + valueNode.length))]
|
||||
};
|
||||
treeItem.iconPath = this.getIcon(valueNode);
|
||||
treeItem.contextValue = valueNode.type;
|
||||
return treeItem;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
select(range: vscode.Range) {
|
||||
@ -80,7 +91,7 @@ export class JsonOutlineProvider implements vscode.TreeDataProvider<json.Node> {
|
||||
}
|
||||
|
||||
private getIcon(node: json.Node): any {
|
||||
let nodeType = this.getNodeType(node);
|
||||
let nodeType = node.type;
|
||||
if (nodeType === 'boolean') {
|
||||
return {
|
||||
light: this.context.asAbsolutePath(path.join('resources', 'light', 'boolean.svg')),
|
||||
@ -102,33 +113,29 @@ export class JsonOutlineProvider implements vscode.TreeDataProvider<json.Node> {
|
||||
return null;
|
||||
}
|
||||
|
||||
private getNodeType(node: json.Node): json.NodeType {
|
||||
if (node.parent.type === 'array') {
|
||||
return node.type;
|
||||
}
|
||||
return node.children[1].type;
|
||||
}
|
||||
|
||||
private getLabel(node: json.Node): string {
|
||||
if (node.parent.type === 'array') {
|
||||
if (node['arrayValue']) {
|
||||
delete node['arrayValue'];
|
||||
if (!node.children) {
|
||||
return node.value.toString();
|
||||
}
|
||||
} else {
|
||||
return node.parent.children.indexOf(node).toString();
|
||||
let prefix = node.parent.children.indexOf(node).toString();
|
||||
if (node.type === 'object') {
|
||||
return prefix + ':{ }';
|
||||
}
|
||||
if (node.type === 'array') {
|
||||
return prefix + ':[ ]';
|
||||
}
|
||||
return prefix + ':' + node.value.toString();
|
||||
}
|
||||
const property = node.children[0].value.toString();
|
||||
if (node.children[1].type === 'object') {
|
||||
return '{ } ' + property;
|
||||
else {
|
||||
const property = node.parent.children[0].value.toString();
|
||||
if (node.type === 'array' || node.type === 'object') {
|
||||
if (node.type === 'object') {
|
||||
return '{ } ' + property;
|
||||
}
|
||||
if (node.type === 'array') {
|
||||
return '[ ] ' + property;
|
||||
}
|
||||
}
|
||||
const value = this.editor.document.getText(new vscode.Range(this.editor.document.positionAt(node.offset), this.editor.document.positionAt(node.offset + node.length)))
|
||||
return `${property}: ${value}`;
|
||||
}
|
||||
if (node.children[1].type === 'array') {
|
||||
return '[ ] ' + property;
|
||||
}
|
||||
const value = this.editor.document.getText(new vscode.Range(this.editor.document.positionAt(node.children[1].offset), this.editor.document.positionAt(node.children[1].offset + node.children[1].length)))
|
||||
return `${property}: ${value}`;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user