bmc-tpl-code-all-around/src/core/TplLinter.ts

94 lines
3.4 KiB
TypeScript
Raw Normal View History

import * as vscode from 'vscode';
import { LinterContext } from './LinterContext';
import { LinterRule } from './rules/LinterRule';
import { SyntaxRule } from './rules/SyntaxRule';
import { BlockRule } from './rules/BlockRule';
export function validateTplDocument(document: vscode.TextDocument, collection: vscode.DiagnosticCollection) {
if (document.languageId !== 'tpl') { return; }
const ctx = new LinterContext();
const config = vscode.workspace.getConfiguration('tpl');
ctx.configuredTplVersion = config.get<number>('version', 23);
const text = document.getText();
const lines = text.split('\n');
// 1. Version prüfen
const versionMatch = text.match(/tpl\s+1\.(\d+)\s+module/);
if (versionMatch) {
ctx.tplVersion = parseInt(versionMatch[1], 10);
if (ctx.tplVersion < ctx.configuredTplVersion) {
const linesToSearch = text.substring(0, versionMatch.index! + 30).split('\n');
ctx.addDiag(linesToSearch.length - 1, 0, versionMatch[0].length, `Das Modul nutzt eine alte TPL Version (1.${ctx.tplVersion}). Aktuell in den Settings definiert ist 1.${ctx.configuredTplVersion}.`, vscode.DiagnosticSeverity.Warning);
}
}
// 2. Regeln laden
const rules: LinterRule[] = [
new SyntaxRule(),
new BlockRule()
];
// 3. Zeilenweise iterieren
for (let i = 0; i < lines.length; i++) {
const rawLine = lines[i];
const line = rawLine.trim();
ctx.resetLineStates();
// Basis-Lexer: Strings & Kommentare tracken (läuft vor den Regeln!)
trackStrings(rawLine, line, ctx);
if (ctx.isInternalStringLine && (ctx.inTripleDouble || ctx.inTripleSingle)) { continue; }
if (line.startsWith('//') || line.startsWith('/*')) {
if (line.startsWith('/*')) { ctx.inMultiLineComment = true; }
continue;
}
if (ctx.inMultiLineComment) {
if (line.includes('*/')) { ctx.inMultiLineComment = false; }
continue;
}
if (line.length === 0) { continue; }
// Regeln anwenden
for (const rule of rules) {
rule.checkLine(line, rawLine, i, ctx, lines); // Hier 'lines' ergänzen!
}
}
// 4. Abschluss-Prüfungen durchführen
for (const rule of rules) {
if (rule.checkEnd) {
rule.checkEnd(lines, ctx);
}
}
// Diagnostics an VS Code übergeben
collection.set(document.uri, ctx.diagnostics);
}
// Interne Hilfsfunktion für den Parser
function trackStrings(rawLine: string, line: string, ctx: LinterContext) {
const tripleDoubleCount = (rawLine.match(/"""/g) || []).length;
const tripleSingleCount = (rawLine.match(/'''/g) || []).length;
if (ctx.inTripleDouble) {
ctx.isInternalStringLine = true;
if (tripleDoubleCount % 2 !== 0) { ctx.inTripleDouble = false; ctx.isClosingString = true; }
} else if (tripleDoubleCount % 2 !== 0) {
ctx.inTripleDouble = true; ctx.justOpenedString = true;
}
if (ctx.inTripleSingle) {
ctx.isInternalStringLine = true;
if (tripleSingleCount % 2 !== 0) { ctx.inTripleSingle = false; ctx.isClosingString = true; }
} else if (tripleSingleCount % 2 !== 0 && !ctx.justOpenedString) {
ctx.inTripleSingle = true; ctx.justOpenedString = true;
}
if (ctx.justOpenedString) {
ctx.stringNeedsSemicolon = !line.startsWith('"""') && !line.startsWith("'''");
}
}