77 lines
3.6 KiB
TypeScript
77 lines
3.6 KiB
TypeScript
import * as vscode from 'vscode';
|
|
import { LinterRule } from './LinterRule';
|
|
import { LinterContext } from '../LinterContext';
|
|
|
|
export class MetadataRule implements LinterRule {
|
|
public checkLine(line: string, rawLine: string, lineIdx: number, ctx: LinterContext, lines: string[]): void {
|
|
if (line.startsWith('metadata') && ctx.inBlock === 'none') {
|
|
ctx.inModuleMetadata = true;
|
|
ctx.hasModuleMetadata = true;
|
|
ctx.moduleMetadataBlockLine = lineIdx;
|
|
ctx.foundModuleMetadata.clear();
|
|
return;
|
|
}
|
|
|
|
if (ctx.inModuleMetadata) {
|
|
const config = vscode.workspace.getConfiguration('tpl');
|
|
|
|
if (line.match(/^origin\b/)) {ctx.foundModuleMetadata.add('origin');}
|
|
if (line.match(/^author\b/)) {ctx.foundModuleMetadata.add('author');}
|
|
if (line.match(/^products\b/)) {ctx.foundModuleMetadata.add('products');}
|
|
if (line.match(/^publishers\b/)) {ctx.foundModuleMetadata.add('publishers');}
|
|
|
|
if (line.match(/^tree_path\b/)) {
|
|
ctx.foundModuleMetadata.add('tree_path');
|
|
if (config.get<boolean>('metadata.require.treePath', true)) {
|
|
this.checkTreePath(line, rawLine, lineIdx, ctx, config);
|
|
}
|
|
}
|
|
|
|
if (line.startsWith('end metadata')) {
|
|
ctx.inModuleMetadata = false;
|
|
this.checkRequiredFields(ctx, config);
|
|
}
|
|
}
|
|
}
|
|
|
|
private checkTreePath(line: string, rawLine: string, lineIdx: number, ctx: LinterContext, config: vscode.WorkspaceConfiguration) {
|
|
const minLevels = config.get<number>('metadata.treePath.minLevels', 3);
|
|
const staticNodes = config.get<string[]>('metadata.treePath.staticNodes', ['Grafing']); // Fallback
|
|
|
|
const match = line.match(/tree_path\s*:=\s*(.*);/);
|
|
if (match) {
|
|
const paths = match[1].split(',').map(s => s.trim().replace(/^['"]|['"]$/g, ''));
|
|
|
|
if (paths.length < minLevels) {
|
|
ctx.addDiag(lineIdx, 0, rawLine.length, `The tree_path must contain at least ${minLevels} levels.`, vscode.DiagnosticSeverity.Error);
|
|
}
|
|
|
|
for (let i = 0; i < staticNodes.length; i++) {
|
|
if (paths[i] !== staticNodes[i]) {
|
|
ctx.addDiag(lineIdx, 0, rawLine.length, `Tree path level ${i + 1} must strictly be '${staticNodes[i]}'.`, vscode.DiagnosticSeverity.Error);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private checkRequiredFields(ctx: LinterContext, config: vscode.WorkspaceConfiguration) {
|
|
const requiredFields: string[] = [];
|
|
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.products', true)) {requiredFields.push('products');}
|
|
if (config.get<boolean>('metadata.require.publishers', true)) {requiredFields.push('publishers');}
|
|
if (config.get<boolean>('metadata.require.treePath', true)) {requiredFields.push('tree_path');}
|
|
|
|
const missing = requiredFields.filter(f => !ctx.foundModuleMetadata.has(f));
|
|
|
|
if (missing.length > 0 && ctx.moduleMetadataBlockLine !== -1) {
|
|
const diag = ctx.addDiag(ctx.moduleMetadataBlockLine, 0, 8, `Missing mandatory module metadata fields: ${missing.join(', ')}`, vscode.DiagnosticSeverity.Error);
|
|
diag.code = 'missing_module_metadata';
|
|
}
|
|
}
|
|
|
|
public checkEnd(lines: string[], ctx: LinterContext): void {
|
|
// empty
|
|
}
|
|
}
|