Skip to content

Commit

Permalink
Register semantic tokens provider. Closes #44.
Browse files Browse the repository at this point in the history
  • Loading branch information
EvgeniyPeshkov committed Sep 20, 2020
1 parent f256843 commit cadcfb9
Showing 1 changed file with 5 additions and 198 deletions.
203 changes: 5 additions & 198 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,212 +327,19 @@ export async function activate(context: vscode.ExtensionContext) {

const enabledLangs: string[] =
vscode.workspace.getConfiguration("syntax").get("highlightLanguages");
let supportedLangs: string[] = [];
let supportedLangs: { language: string }[] = [];
availableGrammars.forEach(lang => {
if (availableParsers.includes(lang) && enabledLangs.includes(lang))
supportedLangs.push(lang);
supportedLangs.push({language: lang});
});

// Term colors
const availableTerms: string[] = [
"type", "scope", "function", "variable", "number", "string", "comment",
"constant", "directive", "control", "operator", "modifier", "punctuation",
];
const enabledTerms: string[] =
vscode.workspace.getConfiguration("syntax").get("highlightTerms");
let supportedTerms: string[] = [];
availableTerms.forEach(term => {
if (enabledTerms.includes(term))
supportedTerms.push(term);
});
if (!vscode.workspace.getConfiguration("syntax").get("highlightComment"))
if (supportedTerms.includes("comment"))
supportedTerms.splice(supportedTerms.indexOf("comment"), 1);

// Debug depth
debugDepth = vscode.workspace.getConfiguration("syntax").get("debugDepth");

// Decoration definitions
const highlightDecors: { [color: string]: vscode.TextEditorDecorationType } = {};
for (const c of supportedTerms)
highlightDecors[c] = vscode.window.
createTextEditorDecorationType({
color: new vscode.ThemeColor("syntax." + c)
});
// Decoration cache
const decorCache: { [doc: string]: { [color: string]: vscode.Range[] } } = {};

// Timer to schedule decoration update and refresh
let updateTimer: NodeJS.Timer | undefined = undefined;
let refreshTimer: NodeJS.Timer | undefined = undefined;
console.log('{Syntax Highlighter} has been activated');

let visibleEditors = vscode.window.visibleTextEditors;
let visibleUris: string[] = [];
let refreshUris: string[] = [];

function refreshDecor() {
for (const e of visibleEditors)
{
const uri = e.document.uri.toString();
if (!refreshUris.includes(uri))
continue;
if (!(uri in decorCache))
continue;
const decorations = decorCache[uri];
for (const c in decorations)
e.setDecorations(highlightDecors[c], decorations[c]);
}
refreshUris = [];
}

function enqueueDecorRefresh() {
if (refreshTimer) {
clearTimeout(refreshTimer);
refreshTimer = undefined;
}
refreshTimer = setTimeout(refreshDecor, 20);
}

function buildDecor(doc: vscode.TextDocument) {
// Document syntax tree
const uri = doc.uri.toString();
if (!(uri in trees))
return;
// Parse syntax tree
const grammar = grammars[doc.languageId];
const terms = grammar.parse(trees[uri]);
// Decorations
let decorations: { [color: string]: vscode.Range[] } = {};
for (const c in highlightDecors)
decorations[c] = [];
// Add decorations for terms
for (const t of terms)
if (t.term in highlightDecors)
decorations[t.term].push(t.range);
// Cache and refresh decorations
decorCache[uri] = decorations;
if (!refreshUris.includes(uri))
refreshUris.push(uri);
}

function updateDecor() {
for (const e of visibleEditors) {
const uri = e.document.uri.toString();
if (!(uri in trees))
continue;
if (uri in decorCache)
continue;
buildDecor(e.document);
}
if (refreshUris.length > 0)
enqueueDecorRefresh();
}

function enqueueDecorUpdate() {
if (updateTimer) {
clearTimeout(updateTimer);
updateTimer = undefined;
}
updateTimer = setTimeout(updateDecor, 20);
}

async function initTree(doc: vscode.TextDocument) {
const lang = doc.languageId;
if (!supportedLangs.includes(lang))
return;
if (!(lang in grammars)) {
grammars[lang] = new Grammar(lang);
await grammars[lang].init();
}
const uri = doc.uri.toString();
trees[uri] = grammars[lang].tree(doc.getText());
enqueueDecorUpdate();
}

function updateTree(doc: vscode.TextDocument) {
const uri = doc.uri.toString();
const lang = doc.languageId;
if (!(uri in trees))
return;

// Update tree
trees[uri] = grammars[lang].tree(doc.getText())

// Invalidate decoration cache and enqueue update
delete decorCache[uri];
if (visibleUris.includes(uri))
enqueueDecorUpdate();
}


// Create trees for already opened documents
for (const doc of vscode.workspace.textDocuments)
await initTree(doc);
enqueueDecorUpdate();

vscode.workspace.onDidOpenTextDocument(async doc => {
await initTree(doc);
}, null, context.subscriptions)

vscode.workspace.onDidCloseTextDocument(doc => {
const uri = doc.uri.toString();
delete trees[uri];
delete decorCache[uri];
if (refreshUris.includes(uri))
refreshUris.splice(refreshUris.indexOf(uri), 1);
}, null, context.subscriptions)

vscode.workspace.onDidChangeTextDocument(event => {
const uri = event.document.uri.toString();
if (!(uri in trees))
return;
if (event.contentChanges.length < 1)
return;
updateTree(event.document);
}, null, context.subscriptions);


// Enumerate already visible editors
visibleEditors = vscode.window.visibleTextEditors;
visibleUris = [];
for (const e of visibleEditors) {
const uri = e.document.uri.toString();
if (!visibleUris.includes(uri))
visibleUris.push(uri);
}

vscode.window.onDidChangeVisibleTextEditors(editors => {
// Flag refresh for new editors
let needUpdate = false;
for (const e of editors) {
const uri = e.document.uri.toString();
if (visibleEditors.includes(e))
continue;
if (!refreshUris.includes(uri))
refreshUris.push(uri);
if (uri in trees)
needUpdate = true;
}

// Set visible editors
visibleEditors = editors;
visibleUris = [];
for (const e of visibleEditors) {
const uri = e.document.uri.toString();
if (!visibleUris.includes(uri))
visibleUris.push(uri);
}

// Enqueue refresh if required
if (needUpdate)
enqueueDecorUpdate();
}, null, context.subscriptions);
context.subscriptions.push(
vscode.languages.registerDocumentSemanticTokensProvider(
supportedLangs, new TokensProvider(), legend));

// Register debug hover providers
// Very useful tool for implementation and fixing of grammars
if (vscode.workspace.getConfiguration("syntax").get("debugHover"))
for (const lang of supportedLangs)
vscode.languages.registerHoverProvider(lang, { provideHover: scopeInfo });

}

0 comments on commit cadcfb9

Please sign in to comment.