linter fixes, fixes after refactoring and error fixing after i made MetadataRule seperate from BlockRule
This commit is contained in:
parent
9dcbf58f3a
commit
387f3793df
|
|
@ -0,0 +1 @@
|
||||||
|
npm run lint -- --fix
|
||||||
|
|
@ -8,7 +8,7 @@ import { IndentationRule } from './rules/IndentationRule'; // 1. Hier importiere
|
||||||
// ... (deine eventuellen anderen Hilfs-Imports wie trackStrings) ...
|
// ... (deine eventuellen anderen Hilfs-Imports wie trackStrings) ...
|
||||||
|
|
||||||
export function validateTplDocument(document: vscode.TextDocument, collection: vscode.DiagnosticCollection) {
|
export function validateTplDocument(document: vscode.TextDocument, collection: vscode.DiagnosticCollection) {
|
||||||
if (document.languageId !== 'tpl') return;
|
if (document.languageId !== 'tpl') {return;}
|
||||||
|
|
||||||
const text = document.getText();
|
const text = document.getText();
|
||||||
const lines = text.split('\n');
|
const lines = text.split('\n');
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ export class IndentationRule implements LinterRule {
|
||||||
|
|
||||||
public checkLine(line: string, rawLine: string, lineIdx: number, ctx: LinterContext, lines: string[]): void {
|
public checkLine(line: string, rawLine: string, lineIdx: number, ctx: LinterContext, lines: string[]): void {
|
||||||
// Leere Zeilen oder Zeilen, die nur aus Leerzeichen/Tabs bestehen, ignorieren
|
// Leere Zeilen oder Zeilen, die nur aus Leerzeichen/Tabs bestehen, ignorieren
|
||||||
if (rawLine.trim().length === 0) return;
|
if (rawLine.trim().length === 0) {return;}
|
||||||
|
|
||||||
// Wenn Tabs drin sind, meckert die SyntaxRule bereits. Das ignorieren wir hier.
|
// Wenn Tabs drin sind, meckert die SyntaxRule bereits. Das ignorieren wir hier.
|
||||||
if (rawLine.includes('\t')) return;
|
if (rawLine.includes('\t')) {return;}
|
||||||
|
|
||||||
const leadingSpacesMatch = rawLine.match(/^ +/);
|
const leadingSpacesMatch = rawLine.match(/^ +/);
|
||||||
const spaceCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;
|
const spaceCount = leadingSpacesMatch ? leadingSpacesMatch[0].length : 0;
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,10 @@ export class MetadataRule implements LinterRule {
|
||||||
const config = vscode.workspace.getConfiguration('tpl');
|
const config = vscode.workspace.getConfiguration('tpl');
|
||||||
|
|
||||||
// Felder erfassen
|
// Felder erfassen
|
||||||
if (line.match(/^origin\b/)) ctx.foundModuleMetadata.add('origin');
|
if (line.match(/^origin\b/)) {ctx.foundModuleMetadata.add('origin');}
|
||||||
if (line.match(/^author\b/)) ctx.foundModuleMetadata.add('author');
|
if (line.match(/^author\b/)) {ctx.foundModuleMetadata.add('author');}
|
||||||
if (line.match(/^products\b/)) ctx.foundModuleMetadata.add('products');
|
if (line.match(/^products\b/)) {ctx.foundModuleMetadata.add('products');}
|
||||||
if (line.match(/^publishers\b/)) ctx.foundModuleMetadata.add('publishers');
|
if (line.match(/^publishers\b/)) {ctx.foundModuleMetadata.add('publishers');}
|
||||||
|
|
||||||
// Tree-Path Sonderprüfung
|
// Tree-Path Sonderprüfung
|
||||||
if (line.match(/^tree_path\b/)) {
|
if (line.match(/^tree_path\b/)) {
|
||||||
|
|
@ -60,11 +60,11 @@ export class MetadataRule implements LinterRule {
|
||||||
|
|
||||||
private checkRequiredFields(ctx: LinterContext, config: vscode.WorkspaceConfiguration) {
|
private checkRequiredFields(ctx: LinterContext, config: vscode.WorkspaceConfiguration) {
|
||||||
const requiredFields: string[] = [];
|
const requiredFields: string[] = [];
|
||||||
if (config.get<boolean>('metadata.require.origin', true)) requiredFields.push('origin');
|
if (config.get<boolean>('metadata.require.origin', true)) {requiredFields.push('origin');}
|
||||||
if (config.get<boolean>('metadata.require.author', true)) requiredFields.push('author');
|
if (config.get<boolean>('metadata.require.author', true)) {requiredFields.push('author');}
|
||||||
if (config.get<boolean>('metadata.require.products', true)) requiredFields.push('products');
|
if (config.get<boolean>('metadata.require.products', true)) {requiredFields.push('products');}
|
||||||
if (config.get<boolean>('metadata.require.publishers', true)) requiredFields.push('publishers');
|
if (config.get<boolean>('metadata.require.publishers', true)) {requiredFields.push('publishers');}
|
||||||
if (config.get<boolean>('metadata.require.treePath', true)) requiredFields.push('tree_path');
|
if (config.get<boolean>('metadata.require.treePath', true)) {requiredFields.push('tree_path');}
|
||||||
|
|
||||||
const missing = requiredFields.filter(f => !ctx.foundModuleMetadata.has(f));
|
const missing = requiredFields.filter(f => !ctx.foundModuleMetadata.has(f));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export class SyntaxRule implements LinterRule {
|
||||||
const commentIdx = cleanLine.indexOf('//');
|
const commentIdx = cleanLine.indexOf('//');
|
||||||
let codePart = commentIdx !== -1 ? cleanLine.substring(0, commentIdx).trim() : cleanLine.trim();
|
let codePart = commentIdx !== -1 ? cleanLine.substring(0, commentIdx).trim() : cleanLine.trim();
|
||||||
|
|
||||||
if (codePart.length === 0) return;
|
if (codePart.length === 0) {return;}
|
||||||
|
|
||||||
let isStructuralKeyword = /^(tpl|pattern|syncmapping|table|definitions?|define|enumeration|configuration|metadata|overview|constants|triggers|mapping|removal|body|end|on|tags|origin|author|products|publishers|tree_path|import|from)\b/.test(codePart);
|
let isStructuralKeyword = /^(tpl|pattern|syncmapping|table|definitions?|define|enumeration|configuration|metadata|overview|constants|triggers|mapping|removal|body|end|on|tags|origin|author|products|publishers|tree_path|import|from)\b/.test(codePart);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { tplBuiltIns } from '../data/TplBuiltIns';
|
||||||
export class TplHoverProvider implements vscode.HoverProvider {
|
export class TplHoverProvider implements vscode.HoverProvider {
|
||||||
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover | null> {
|
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover | null> {
|
||||||
const range = document.getWordRangeAtPosition(position, /[a-zA-Z0-9_.]+/);
|
const range = document.getWordRangeAtPosition(position, /[a-zA-Z0-9_.]+/);
|
||||||
if (!range) return null;
|
if (!range) {return null;}
|
||||||
|
|
||||||
const word = document.getText(range);
|
const word = document.getText(range);
|
||||||
const text = document.getText();
|
const text = document.getText();
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ export class MetadataFix implements TplQuickFix {
|
||||||
const missingFields = missingFieldsStr.split(', ');
|
const missingFields = missingFieldsStr.split(', ');
|
||||||
|
|
||||||
let insertText = '';
|
let insertText = '';
|
||||||
if (missingFields.includes('origin')) insertText += ` origin := '${origin}';\n`;
|
if (missingFields.includes('origin')) {insertText += ` origin := '${origin}';\n`;}
|
||||||
if (missingFields.includes('author')) insertText += ` author := '${author}';\n`;
|
if (missingFields.includes('author')) {insertText += ` author := '${author}';\n`;}
|
||||||
if (missingFields.includes('products')) insertText += ` products := 'TODO_Product';\n`;
|
if (missingFields.includes('products')) {insertText += ` products := 'TODO_Product';\n`;}
|
||||||
if (missingFields.includes('publishers')) insertText += ` publishers := '${publisher}';\n`;
|
if (missingFields.includes('publishers')) {insertText += ` publishers := '${publisher}';\n`;}
|
||||||
if (missingFields.includes('tree_path')) insertText += ` tree_path := '${treePathBase}', 'TODO_Category', 'TODO_Subcategory';\n`;
|
if (missingFields.includes('tree_path')) {insertText += ` tree_path := '${treePathBase}', 'TODO_Category', 'TODO_Subcategory';\n`;}
|
||||||
|
|
||||||
fix.edit.insert(document.uri, new vscode.Position(diagnostic.range.start.line + 1, 0), insertText);
|
fix.edit.insert(document.uri, new vscode.Position(diagnostic.range.start.line + 1, 0), insertText);
|
||||||
fix.diagnostics = [diagnostic];
|
fix.diagnostics = [diagnostic];
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,15 @@ import { CompletionStrategy } from './CompletionStrategy';
|
||||||
|
|
||||||
export class SnippetCompletion implements CompletionStrategy {
|
export class SnippetCompletion implements CompletionStrategy {
|
||||||
public async provideCompletions(document: vscode.TextDocument, position: vscode.Position, linePrefix: string): Promise<vscode.CompletionItem[] | undefined> {
|
public async provideCompletions(document: vscode.TextDocument, position: vscode.Position, linePrefix: string): Promise<vscode.CompletionItem[] | undefined> {
|
||||||
// Bei Modul-Aufrufen (Punkt) keine Snippets feuern
|
|
||||||
if (linePrefix.match(/\.[a-zA-Z0-9_]*$/)) { return undefined; }
|
if (linePrefix.match(/\.[a-zA-Z0-9_]*$/)) { return undefined; }
|
||||||
|
|
||||||
const items: vscode.CompletionItem[] = [];
|
const items: vscode.CompletionItem[] = [];
|
||||||
|
|
||||||
// 1. Kontext herausfinden (Sind wir in einem Pattern oder Syncmapping?)
|
|
||||||
const textBeforeCursor = document.getText(new vscode.Range(new vscode.Position(0, 0), position));
|
const textBeforeCursor = document.getText(new vscode.Range(new vscode.Position(0, 0), position));
|
||||||
const inPattern = textBeforeCursor.lastIndexOf('pattern ') > textBeforeCursor.lastIndexOf('end pattern;');
|
const inPattern = textBeforeCursor.lastIndexOf('pattern ') > textBeforeCursor.lastIndexOf('end pattern;');
|
||||||
const inSyncmapping = textBeforeCursor.lastIndexOf('syncmapping ') > textBeforeCursor.lastIndexOf('end syncmapping;');
|
const inSyncmapping = textBeforeCursor.lastIndexOf('syncmapping ') > textBeforeCursor.lastIndexOf('end syncmapping;');
|
||||||
const inBlock = inPattern || inSyncmapping;
|
const inBlock = inPattern || inSyncmapping;
|
||||||
|
|
||||||
// 2. Settings laden
|
|
||||||
const config = vscode.workspace.getConfiguration('tpl');
|
const config = vscode.workspace.getConfiguration('tpl');
|
||||||
const author = config.get<string>('metadata.author', 'Kuro');
|
const author = config.get<string>('metadata.author', 'Kuro');
|
||||||
const origin = config.get<string>('metadata.origin', 'Custom');
|
const origin = config.get<string>('metadata.origin', 'Custom');
|
||||||
|
|
@ -35,47 +32,38 @@ export class SnippetCompletion implements CompletionStrategy {
|
||||||
treePathStr += `'\${${snippetTabIdx}:Level_${i+1}}'`;
|
treePathStr += `'\${${snippetTabIdx}:Level_${i+1}}'`;
|
||||||
snippetTabIdx++;
|
snippetTabIdx++;
|
||||||
}
|
}
|
||||||
if (i < minLevels - 1) treePathStr += ', ';
|
if (i < minLevels - 1) {treePathStr += ', ';}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamischer Metadata-String
|
// Dynamischer Modul-Metadata-Block
|
||||||
let metadataBlock = 'metadata\n';
|
let metadataBlock = 'metadata\n';
|
||||||
if (config.get<boolean>('metadata.require.origin', true)) metadataBlock += ` origin := '${origin}';\n`;
|
if (config.get<boolean>('metadata.require.origin', true)) {metadataBlock += ` origin := '${origin}';\n`;}
|
||||||
if (config.get<boolean>('metadata.require.treePath', true)) metadataBlock += ` tree_path := ${treePathStr};\n`;
|
if (config.get<boolean>('metadata.require.treePath', true)) {metadataBlock += ` tree_path := ${treePathStr};\n`;}
|
||||||
if (config.get<boolean>('metadata.require.products', true)) metadataBlock += ` products := '\${${snippetTabIdx++}:Product}';\n`;
|
if (config.get<boolean>('metadata.require.products', true)) {metadataBlock += ` products := '\${${snippetTabIdx++}:Product}';\n`;}
|
||||||
if (config.get<boolean>('metadata.require.publishers', true)) metadataBlock += ` publishers := '${publisher}';\n`;
|
if (config.get<boolean>('metadata.require.publishers', true)) {metadataBlock += ` publishers := '${publisher}';\n`;}
|
||||||
if (config.get<boolean>('metadata.require.author', true)) metadataBlock += ` author := '${author}';\n`;
|
if (config.get<boolean>('metadata.require.author', true)) {metadataBlock += ` author := '${author}';\n`;}
|
||||||
metadataBlock += 'end metadata;';
|
metadataBlock += 'end metadata;';
|
||||||
|
|
||||||
// ==========================================
|
|
||||||
// SNIPPETS FÜR DIE MODUL-EBENE (Außerhalb)
|
|
||||||
// ==========================================
|
|
||||||
if (!inBlock) {
|
if (!inBlock) {
|
||||||
const skeleton = new vscode.CompletionItem('tpl_skeleton', vscode.CompletionItemKind.Snippet);
|
const skeleton = new vscode.CompletionItem('tpl_skeleton', vscode.CompletionItemKind.Snippet);
|
||||||
skeleton.detail = "Generiert ein frisches TPL Modul";
|
skeleton.detail = "Generiert ein frisches TPL Modul";
|
||||||
skeleton.insertText = new vscode.SnippetString(
|
skeleton.insertText = new vscode.SnippetString(
|
||||||
`tpl 1.\${1:${version}} module \${2:MyModule};\n\n` +
|
`tpl 1.\${${snippetTabIdx++}:${version}} module \${${snippetTabIdx++}:MyModule};\n\n` +
|
||||||
`metadata\n` +
|
`${metadataBlock}\n\n` +
|
||||||
` origin := '${origin}';\n` +
|
`pattern \${${snippetTabIdx++}:MyPattern} 1.0\n` +
|
||||||
` tree_path := '${treePathBase}', '\${3:Category}', '\${4:Subcategory}';\n` +
|
` """\n \${${snippetTabIdx++}:Beschreibung des Patterns}\n """\n` +
|
||||||
` products := '\${5:Product}';\n` +
|
|
||||||
` publishers := '${publisher}';\n` +
|
|
||||||
` author := '${author}';\n` +
|
|
||||||
`end metadata;\n\n` +
|
|
||||||
`pattern \${6:MyPattern} 1.0\n` +
|
|
||||||
` """\n \${7:Beschreibung des Patterns}\n """\n` +
|
|
||||||
` metadata\n` +
|
` metadata\n` +
|
||||||
` publishers := '${publisher}';\n` +
|
` publishers := '${publisher}';\n` +
|
||||||
` tags := '\${8:Tags}';\n` +
|
` tags := '\${${snippetTabIdx++}:Tags}';\n` +
|
||||||
` end metadata;\n\n` +
|
` end metadata;\n\n` +
|
||||||
` overview\n` +
|
` overview\n` +
|
||||||
` tags \${9:Tags};\n` +
|
` tags \${${snippetTabIdx++}:Tags};\n` +
|
||||||
` end overview;\n\n` +
|
` end overview;\n\n` +
|
||||||
` constants\n` +
|
` constants\n` +
|
||||||
` \${10:const_name} := '\${11:value}';\n` +
|
` \${${snippetTabIdx++}:const_name} := '\${${snippetTabIdx++}:value}';\n` +
|
||||||
` end constants;\n\n` +
|
` end constants;\n\n` +
|
||||||
` triggers\n` +
|
` triggers\n` +
|
||||||
` on process := SoftwareInstance created, confirmed where type = '\${12:Type}';\n` +
|
` on process := SoftwareInstance created, confirmed where type = '\${${snippetTabIdx++}:Type}';\n` +
|
||||||
` end triggers;\n\n` +
|
` end triggers;\n\n` +
|
||||||
` body\n` +
|
` body\n` +
|
||||||
` log.debug("Start pattern %pattern_name%");\n` +
|
` log.debug("Start pattern %pattern_name%");\n` +
|
||||||
|
|
@ -87,21 +75,10 @@ export class SnippetCompletion implements CompletionStrategy {
|
||||||
|
|
||||||
const modMeta = new vscode.CompletionItem('metadata', vscode.CompletionItemKind.Snippet);
|
const modMeta = new vscode.CompletionItem('metadata', vscode.CompletionItemKind.Snippet);
|
||||||
modMeta.detail = "Modul-Metadaten Block (Pflichtfelder)";
|
modMeta.detail = "Modul-Metadaten Block (Pflichtfelder)";
|
||||||
modMeta.insertText = new vscode.SnippetString(
|
modMeta.insertText = new vscode.SnippetString(`${metadataBlock}\n$0`);
|
||||||
`metadata\n` +
|
|
||||||
` origin := '${origin}';\n` +
|
|
||||||
` tree_path := '${treePathBase}', '\${1:Category}', '\${2:Subcategory}';\n` +
|
|
||||||
` products := '\${3:Product}';\n` +
|
|
||||||
` publishers := '${publisher}';\n` +
|
|
||||||
` author := '${author}';\n` +
|
|
||||||
`end metadata;\n$0`
|
|
||||||
);
|
|
||||||
items.push(modMeta);
|
items.push(modMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================
|
|
||||||
// SNIPPETS FÜR DIE PATTERN-EBENE (Innerhalb)
|
|
||||||
// ==========================================
|
|
||||||
if (inBlock) {
|
if (inBlock) {
|
||||||
const patMeta = new vscode.CompletionItem('metadata', vscode.CompletionItemKind.Snippet);
|
const patMeta = new vscode.CompletionItem('metadata', vscode.CompletionItemKind.Snippet);
|
||||||
patMeta.detail = "Pattern-Metadaten Block";
|
patMeta.detail = "Pattern-Metadaten Block";
|
||||||
|
|
@ -114,9 +91,6 @@ export class SnippetCompletion implements CompletionStrategy {
|
||||||
items.push(patMeta);
|
items.push(patMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================
|
|
||||||
// ALLGEMEINE SNIPPETS (Überall gültig)
|
|
||||||
// ==========================================
|
|
||||||
const ifSnippet = new vscode.CompletionItem('if', vscode.CompletionItemKind.Snippet);
|
const ifSnippet = new vscode.CompletionItem('if', vscode.CompletionItemKind.Snippet);
|
||||||
ifSnippet.insertText = new vscode.SnippetString(`if \${1:condition} then\n $0\nend if;`);
|
ifSnippet.insertText = new vscode.SnippetString(`if \${1:condition} then\n $0\nend if;`);
|
||||||
items.push(ifSnippet);
|
items.push(ifSnippet);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ function createMockDoc(text: string): any {
|
||||||
}
|
}
|
||||||
|
|
||||||
suite('Completion Provider Test Suite', () => {
|
suite('Completion Provider Test Suite', () => {
|
||||||
test('SnippetCompletion: Kontext-Check (Kein if außerhalb des Bodys)', () => {
|
test('SnippetCompletion: Kontext-Check (Kein if außerhalb des Bodys)', async () => {
|
||||||
const strategy = new SnippetCompletion();
|
const strategy = new SnippetCompletion();
|
||||||
|
|
||||||
// Simuliert, dass wir im "metadata" Block tippen
|
// Simuliert, dass wir im "metadata" Block tippen
|
||||||
|
|
@ -22,14 +22,14 @@ suite('Completion Provider Test Suite', () => {
|
||||||
const mockDoc = createMockDoc(docText);
|
const mockDoc = createMockDoc(docText);
|
||||||
const position = new vscode.Position(2, 4); // Zeile 2, Cursor am Ende
|
const position = new vscode.Position(2, 4); // Zeile 2, Cursor am Ende
|
||||||
|
|
||||||
const result = strategy.provideCompletions(mockDoc, position, ' ');
|
const result = await strategy.provideCompletions(mockDoc, position, ' ');
|
||||||
|
|
||||||
assert.ok(result !== undefined);
|
assert.ok(result !== undefined);
|
||||||
const hasIf = result.some(item => item.label === 'if');
|
const hasIf = result!.some(item => item.label === 'if');
|
||||||
assert.strictEqual(hasIf, false, "Darf kein 'if' im metadata Block vorschlagen");
|
assert.strictEqual(hasIf, false, "Darf kein 'if' im metadata Block vorschlagen");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('SnippetCompletion: Vorschläge im Body korrekt', () => {
|
test('SnippetCompletion: Vorschläge im Body korrekt', async () => {
|
||||||
const strategy = new SnippetCompletion();
|
const strategy = new SnippetCompletion();
|
||||||
|
|
||||||
// Simuliert, dass wir im "body" tippen
|
// Simuliert, dass wir im "body" tippen
|
||||||
|
|
@ -37,10 +37,10 @@ suite('Completion Provider Test Suite', () => {
|
||||||
const mockDoc = createMockDoc(docText);
|
const mockDoc = createMockDoc(docText);
|
||||||
const position = new vscode.Position(2, 4);
|
const position = new vscode.Position(2, 4);
|
||||||
|
|
||||||
const result = strategy.provideCompletions(mockDoc, position, ' ');
|
const result = await strategy.provideCompletions(mockDoc, position, ' ');
|
||||||
|
|
||||||
assert.ok(result !== undefined);
|
assert.ok(result !== undefined);
|
||||||
const hasIf = result.some(item => item.label === 'if');
|
const hasIf = result!.some(item => item.label === 'if');
|
||||||
assert.strictEqual(hasIf, true, "Muss 'if' im Body vorschlagen");
|
assert.strictEqual(hasIf, true, "Muss 'if' im Body vorschlagen");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ suite('Completion Provider Test Suite', () => {
|
||||||
const result = await strategy.provideCompletions(mockDoc, position, 'do');
|
const result = await strategy.provideCompletions(mockDoc, position, 'do');
|
||||||
|
|
||||||
assert.ok(result !== undefined);
|
assert.ok(result !== undefined);
|
||||||
const funcItem = result.find(item => item.label === 'my_tools.doWork');
|
const funcItem = result!.find(item => item.label === 'my_tools.doWork');
|
||||||
assert.ok(funcItem !== undefined, "Muss die Methode inkl. Namespace extrahieren");
|
assert.ok(funcItem !== undefined, "Muss die Methode inkl. Namespace extrahieren");
|
||||||
|
|
||||||
// Prüft, ob das generierte Snippet das Auto-Semikolon und den $0 Cursor hat
|
// Prüft, ob das generierte Snippet das Auto-Semikolon und den $0 Cursor hat
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue