117 lines
2.4 KiB
JavaScript
117 lines
2.4 KiB
JavaScript
"use strict";
|
|
|
|
const vscode = require("vscode");
|
|
|
|
const COMPONENT_DECLARATION = /^\s*(component|layout)\s+([A-Za-z_$][\w$]*)\s*\{/gm;
|
|
|
|
function getTagAtPosition(document, position) {
|
|
const range = document.getWordRangeAtPosition(position, /[A-Za-z_$][\w$]*/);
|
|
|
|
if (!range) {
|
|
return null;
|
|
}
|
|
|
|
const name = document.getText(range);
|
|
|
|
if (!/^[A-Z][A-Za-z0-9_$]*$/.test(name)) {
|
|
return null;
|
|
}
|
|
|
|
const line = document.lineAt(position.line).text;
|
|
const offset = document.offsetAt(position);
|
|
const lineStart = document.offsetAt(new vscode.Position(position.line, 0));
|
|
|
|
const characterOffset = offset - lineStart;
|
|
const before = line.slice(0, characterOffset);
|
|
const after = line.slice(characterOffset);
|
|
|
|
const insideTag = before.lastIndexOf("<") > before.lastIndexOf(">") && after.includes(">");
|
|
|
|
if (!insideTag) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
name,
|
|
range,
|
|
};
|
|
}
|
|
|
|
async function findDeclaration(name) {
|
|
const files = await vscode.workspace.findFiles(
|
|
"**/*.wrn",
|
|
"**/{node_modules,dist,.wrnexus,.git}/**",
|
|
);
|
|
|
|
const matches = [];
|
|
|
|
for (const uri of files) {
|
|
let document;
|
|
|
|
try {
|
|
document = await vscode.workspace.openTextDocument(uri);
|
|
} catch {
|
|
continue;
|
|
}
|
|
|
|
const source = document.getText();
|
|
|
|
COMPONENT_DECLARATION.lastIndex = 0;
|
|
|
|
let match;
|
|
|
|
while ((match = COMPONENT_DECLARATION.exec(source)) !== null) {
|
|
const declarationName = match[2];
|
|
|
|
if (declarationName !== name) {
|
|
continue;
|
|
}
|
|
|
|
const nameOffset = match.index + match[0].indexOf(declarationName);
|
|
|
|
const start = document.positionAt(nameOffset);
|
|
const end = document.positionAt(nameOffset + declarationName.length);
|
|
|
|
matches.push(new vscode.Location(uri, new vscode.Range(start, end)));
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
async function provideDefinition(document, position) {
|
|
const tag = getTagAtPosition(document, position);
|
|
|
|
if (!tag) {
|
|
return null;
|
|
}
|
|
|
|
const matches = await findDeclaration(tag.name);
|
|
|
|
if (matches.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return matches.length === 1 ? matches[0] : matches;
|
|
}
|
|
|
|
function registerDefinitionProvider(context) {
|
|
const disposable = vscode.languages.registerDefinitionProvider(
|
|
{
|
|
language: "wrn",
|
|
},
|
|
{
|
|
provideDefinition,
|
|
},
|
|
);
|
|
|
|
context.subscriptions.push(disposable);
|
|
}
|
|
|
|
module.exports = {
|
|
findDeclaration,
|
|
getTagAtPosition,
|
|
provideDefinition,
|
|
registerDefinitionProvider,
|
|
};
|