2026-10-11 02:31:12 +00:00
|
|
|
import * as vscode from 'vscode';
|
|
|
|
|
import { LinterContext } from './LinterContext';
|
|
|
|
|
import { SyntaxRule } from './rules/SyntaxRule';
|
|
|
|
|
import { BlockRule } from './rules/BlockRule';
|
2026-10-18 01:03:33 +00:00
|
|
|
import { MetadataRule } from './rules/MetadataRule';
|
|
|
|
|
import { IndentationRule } from './rules/IndentationRule'; // 1. Hier importieren
|
|
|
|
|
|
|
|
|
|
// ... (deine eventuellen anderen Hilfs-Imports wie trackStrings) ...
|
2026-10-11 02:31:12 +00:00
|
|
|
|
|
|
|
|
export function validateTplDocument(document: vscode.TextDocument, collection: vscode.DiagnosticCollection) {
|
2026-10-18 01:03:33 +00:00
|
|
|
if (document.languageId !== 'tpl') return;
|
2026-10-11 02:31:12 +00:00
|
|
|
|
|
|
|
|
const text = document.getText();
|
|
|
|
|
const lines = text.split('\n');
|
2026-10-18 01:03:33 +00:00
|
|
|
const ctx = new LinterContext();
|
2026-10-11 02:31:12 +00:00
|
|
|
|
2026-10-18 01:03:33 +00:00
|
|
|
// 2. Hier nur die 3 existierenden Regeln reinlegen (MetadataRule entfernt!)
|
|
|
|
|
const rules = [
|
2026-10-11 02:31:12 +00:00
|
|
|
new SyntaxRule(),
|
2026-10-18 01:03:33 +00:00
|
|
|
new MetadataRule(),
|
|
|
|
|
new BlockRule(),
|
|
|
|
|
new IndentationRule()
|
2026-10-11 02:31:12 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
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) {
|
2026-10-18 01:03:33 +00:00
|
|
|
rule.checkLine(line, rawLine, i, ctx, lines);
|
2026-10-11 02:31:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const rule of rules) {
|
|
|
|
|
rule.checkEnd(lines, ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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("'''");
|
|
|
|
|
}
|
|
|
|
|
}
|