feat(core): mix模式下使用diff去修改代码防止触发整个文件代码高亮的重新构建

This commit is contained in:
王立帮
2026-01-23 10:06:04 +08:00
parent 7fdd11b598
commit 51d5a286f7
31 changed files with 6378 additions and 46 deletions

View File

@@ -0,0 +1,141 @@
importScripts('./tree-sitter.js');
importScripts('../../../../web-modules/workerpool.min.js');
const terms = [
'type',
'scope',
'function',
'variable',
'number',
'string',
'comment',
'constant',
'directive',
'control',
'operator',
'modifier',
'punctuation'
];
let parser;
let tree = null;
let language = null;
class Language {
constructor(grammarJson) {
this.simpleTerms = {};
this.complexTerms = [];
this.complexScopes = {};
for (const t in grammarJson.simpleTerms)
this.simpleTerms[t] = grammarJson.simpleTerms[t];
for (const t in grammarJson.complexTerms)
this.complexTerms[t] = grammarJson.complexTerms[t];
for (const t in grammarJson.complexScopes)
this.complexScopes[t] = grammarJson.complexScopes[t];
this.complexDepth = 0;
this.complexOrder = false;
for (const s in this.complexScopes) {
const depth = s.split('>').length;
if (depth > this.complexDepth)
this.complexDepth = depth;
if (s.indexOf('[') >= 0)
this.complexOrder = true;
}
this.complexDepth--;
}
}
async function init(languageWasmPath, grammarJson) {
await TreeSitter.init();
parser = new TreeSitter();
const lang = await TreeSitter.Language.load(languageWasmPath);
console.log(lang.version)
parser.setLanguage(lang);
language = new Language(grammarJson);
tree = null;
}
function buildDecorations(tree) {
const result = [];
const stack = [];
let node = tree.rootNode.firstChild;
while (stack.length > 0 || node) {
if (node) {
stack.push(node);
node = node.firstChild;
}
else {
node = stack.pop();
let type = node.type;
if (!node.isNamed())
type = '"' + type + '"';
let term = null;
if (!language.complexTerms.includes(type)) {
term = language.simpleTerms[type];
}
else {
let desc = type;
let scopes = [desc];
let parent = node.parent;
for (let i = 0; i < language.complexDepth && parent; i++) {
let parentType = parent.type;
if (!parent.isNamed())
parentType = '"' + parentType + '"';
desc = parentType + ' > ' + desc;
scopes.push(desc);
parent = parent.parent;
}
if (language.complexOrder) {
let index = 0;
let sibling = node.previousSibling;
while (sibling) {
if (sibling.type === node.type)
index++;
sibling = sibling.previousSibling;
}
let rindex = -1;
sibling = node.nextSibling;
while (sibling) {
if (sibling.type === node.type)
rindex--;
sibling = sibling.nextSibling;
}
const orderScopes = [];
for (let i = 0; i < scopes.length; i++)
orderScopes.push(scopes[i], scopes[i] + '[' + index + ']', scopes[i] + '[' + rindex + ']');
scopes = orderScopes;
}
for (const d of scopes)
if (d in language.complexScopes)
term = language.complexScopes[d];
}
if (terms.includes(term)) {
if (!result[term]) {
result[term] = [];
}
result[term].push({
startLineNumber: node.startPosition.row + 1,
startColumn: node.startPosition.column + 1,
endLineNumber: node.endPosition.row + 1,
endColumn: node.endPosition.column + 1
});
}
node = node.nextSibling;
}
}
return result;
}
function update(text) {
const tree = parser.parse(text);
return buildDecorations(tree);
}
workerpool.worker({
init,
update
});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff