Skip to content

Commit

Permalink
工作区符号
Browse files Browse the repository at this point in the history
  • Loading branch information
sumneko committed Jul 8, 2024
1 parent f06d530 commit 05125a5
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 93 deletions.
31 changes: 30 additions & 1 deletion src/editorTable/editorTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Table } from "../constants";
import { env } from "../env";
import * as vscode from "vscode";
import * as y3 from 'y3-helper';
import { throttle } from "../utility/decorators";
import { queue, throttle } from "../utility/decorators";
import * as jsonc from 'jsonc-parser';

const template_dir = 'template\\json_template';
Expand Down Expand Up @@ -456,3 +456,32 @@ export async function getObject(uri: vscode.Uri): Promise<EditorObject | undefin
obj.json = file.string;
return obj;
}

class Manager {
@queue()
async getAllObjects() {
let allObjects: EditorObject[] = [];
let promises: Promise<any>[] = [];
for (const tableName in Table.name.fromCN) {
const table = openTable(tableName as Table.NameCN);
table.getList().then((list) => {
for (const key of list) {
let promise = table.get(key).then((obj) => obj && allObjects.push(obj));
promises.push(promise);
}
});
}
await Promise.allSettled(promises);
allObjects.sort((a, b) => a.key - b.key);
return allObjects;
}
}

const ManagerInstance = new Manager();

export async function getAllObjects() {
return await ManagerInstance.getAllObjects();
}

export function init() {
}
4 changes: 2 additions & 2 deletions src/editorTable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ export * from './types';
export * from './CSV/CSVimporter';
export * from './CSV/CSVeditor';
import { test } from './EXCEL/test';
import * as editorTable from './editorTable';
import * as language from './language';
import * as languageFeature from './languageFeature';
import * as treeView from './treeView';
import * as workspaceSymbol from './workspaceSymbol';

vscode.commands.registerCommand('y3-helper.testExcel', () => {
test();
});

export function init() {
editorTable.init();
language.init();
treeView.init();
languageFeature.init();
workspaceSymbol.init();
}
2 changes: 2 additions & 0 deletions src/editorTable/languageFeature/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import * as documentManager from './documentManager';
import * as documentSymbol from './documentSymbol';
import * as workspaceSymbol from './workspaceSymbol';
import * as hover from './hover';
import * as inlayHints from './inlayHints';

export function init() {
documentManager.init();
documentSymbol.init();
workspaceSymbol.init();
hover.init();
inlayHints.init();
}
141 changes: 141 additions & 0 deletions src/editorTable/languageFeature/workspaceSymbol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import * as vscode from 'vscode';
import * as y3 from 'y3-helper';

interface ObjectResult {
object: y3.table.EditorObject;
query: string;
other: string;
}

interface FieldResult {
objectResult: ObjectResult;
query: string;
other: string;
}

class ObjectInfomation extends vscode.SymbolInformation {
constructor(objectResult: ObjectResult) {
super(
objectResult.query,
vscode.SymbolKind.File,
`${objectResult.object.tableName}(${objectResult.other})`,
new vscode.Location(
objectResult.object.uri!,
new vscode.Position(0, 0),
),
);
}
}

class FieldInfomation extends vscode.SymbolInformation {
constructor(private fieldResult: FieldResult, sep: string) {
super(
`${fieldResult.objectResult.query}${sep}${fieldResult.query}`,
vscode.SymbolKind.Field,
`${fieldResult.objectResult.object.tableName}(${fieldResult.objectResult.other}${sep}${fieldResult.other})`,
new vscode.Location(
fieldResult.objectResult.object.uri!,
new vscode.Position(0, 0),
),
);
}
}

class Provider implements vscode.WorkspaceSymbolProvider {
async provideWorkspaceSymbols(query: string, token: vscode.CancellationToken) {
if (token.isCancellationRequested) {
return;
}
let allObjects = await y3.table.getAllObjects();
if (token.isCancellationRequested) {
return;
}
let matchResult = query.match(/^([^\.\/]*)([\.\/]?)([^\.\/]*)?$/);
if (!matchResult) {
return;
}
let [_, name, sep, field] = matchResult;
let objectResults = this.searchObject(allObjects, name);
if (objectResults.length === 0) {
return;
}
if (!sep) {
let results = objectResults.map((objectResult) => new ObjectInfomation(objectResult));
return results;
}
let fieldResults = this.searchObjectFields(objectResults, field ?? '');
let results = fieldResults.map((FieldResult) => new FieldInfomation(FieldResult, sep));
return results;
}

private compileString(str: string) {
let result: { [key: number]: number } = {};
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
result[code] = (result[code] ?? 0) + 1;
}
return result;
}

private matchString(queryChars: { [key: number]: number }, target: string) {
const targetChars = this.compileString(target);
for (const code in queryChars) {
if (!targetChars[code] || targetChars[code] < queryChars[code]) {
return false;
}
}
return true;
}

private searchObject(objects: y3.table.EditorObject[], query: string) {
const queryChars = this.compileString(query);
let result: ObjectResult[] = [];
for (const object of objects) {
if (this.matchString(queryChars, object.key.toString())) {
result.push({
object,
query: object.key.toString(),
other: object.name,
});
} else if (this.matchString(queryChars, object.name)) {
result.push({
object,
query: object.name,
other: object.key.toString(),
});
}
}
return result;
}

private searchObjectFields(objects: ObjectResult[], query: string) {
const queryChars = this.compileString(query);
let result: FieldResult[] = [];
for (const objectResult of objects) {
for (const field of objectResult.object.listFields()) {
const fieldInfo = objectResult.object.getFieldInfo(field);
if (!fieldInfo) {
continue;
}
if (fieldInfo.desc && this.matchString(queryChars, fieldInfo.desc)) {
result.push({
objectResult,
query: fieldInfo.desc,
other: field,
});
} else if (this.matchString(queryChars, field)) {
result.push({
objectResult,
query: field,
other: fieldInfo.desc ?? '',
});
}
}
}
return result;
}
}

export function init() {
vscode.languages.registerWorkspaceSymbolProvider(new Provider());
}
90 changes: 0 additions & 90 deletions src/editorTable/workspaceSymbol.ts

This file was deleted.

0 comments on commit 05125a5

Please sign in to comment.