@birdcc/linter 0.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oxfmtrc.json +16 -0
- package/LICENSE +674 -0
- package/README.md +210 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/bgp.d.ts +5 -0
- package/dist/rules/bgp.d.ts.map +1 -0
- package/dist/rules/bgp.js +131 -0
- package/dist/rules/bgp.js.map +1 -0
- package/dist/rules/catalog.d.ts +14 -0
- package/dist/rules/catalog.d.ts.map +1 -0
- package/dist/rules/catalog.js +61 -0
- package/dist/rules/catalog.js.map +1 -0
- package/dist/rules/cfg.d.ts +5 -0
- package/dist/rules/cfg.d.ts.map +1 -0
- package/dist/rules/cfg.js +264 -0
- package/dist/rules/cfg.js.map +1 -0
- package/dist/rules/net.d.ts +5 -0
- package/dist/rules/net.d.ts.map +1 -0
- package/dist/rules/net.js +140 -0
- package/dist/rules/net.js.map +1 -0
- package/dist/rules/normalize.d.ts +6 -0
- package/dist/rules/normalize.d.ts.map +1 -0
- package/dist/rules/normalize.js +65 -0
- package/dist/rules/normalize.js.map +1 -0
- package/dist/rules/ospf.d.ts +5 -0
- package/dist/rules/ospf.d.ts.map +1 -0
- package/dist/rules/ospf.js +136 -0
- package/dist/rules/ospf.js.map +1 -0
- package/dist/rules/shared.d.ts +46 -0
- package/dist/rules/shared.d.ts.map +1 -0
- package/dist/rules/shared.js +184 -0
- package/dist/rules/shared.js.map +1 -0
- package/dist/rules/sym.d.ts +5 -0
- package/dist/rules/sym.d.ts.map +1 -0
- package/dist/rules/sym.js +188 -0
- package/dist/rules/sym.js.map +1 -0
- package/dist/rules/type.d.ts +5 -0
- package/dist/rules/type.d.ts.map +1 -0
- package/dist/rules/type.js +130 -0
- package/dist/rules/type.js.map +1 -0
- package/package.json +41 -0
- package/src/index.ts +155 -0
- package/src/rules/bgp.ts +239 -0
- package/src/rules/catalog.ts +80 -0
- package/src/rules/cfg.ts +562 -0
- package/src/rules/net.ts +262 -0
- package/src/rules/normalize.ts +90 -0
- package/src/rules/ospf.ts +221 -0
- package/src/rules/shared.ts +354 -0
- package/src/rules/sym.ts +342 -0
- package/src/rules/type.ts +210 -0
- package/test/linter.bgp-ospf.test.ts +129 -0
- package/test/linter.migration.test.ts +66 -0
- package/test/linter.net-type.test.ts +132 -0
- package/test/linter.sym-cfg.test.ts +224 -0
- package/test/linter.test.ts +21 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { createProtocolDiagnostic, createRuleDiagnostic, isProtocolType, protocolDeclarations, protocolOtherTextEntries, } from "./shared.js";
|
|
2
|
+
const BACKBONE_AREA_IDS = new Set(["0", "0.0.0.0"]);
|
|
3
|
+
const normalizeAreaId = (value) => value.trim().toLowerCase();
|
|
4
|
+
const isBackboneArea = (value) => BACKBONE_AREA_IDS.has(normalizeAreaId(value));
|
|
5
|
+
const parseAreaSegments = (text, range) => {
|
|
6
|
+
const segments = [];
|
|
7
|
+
const consumedRanges = [];
|
|
8
|
+
const blockPattern = /\barea\s+([^\s{;]+)([^{};]*)\{/gi;
|
|
9
|
+
let matched = blockPattern.exec(text);
|
|
10
|
+
while (matched) {
|
|
11
|
+
const matchedText = matched[0] ?? "";
|
|
12
|
+
const areaId = normalizeAreaId(matched[1] ?? "");
|
|
13
|
+
const header = (matched[2] ?? "").trim();
|
|
14
|
+
const openBraceIndex = (matched.index ?? 0) + matchedText.length - 1;
|
|
15
|
+
let cursor = openBraceIndex + 1;
|
|
16
|
+
let depth = 1;
|
|
17
|
+
while (cursor < text.length && depth > 0) {
|
|
18
|
+
if (text[cursor] === "{") {
|
|
19
|
+
depth += 1;
|
|
20
|
+
}
|
|
21
|
+
else if (text[cursor] === "}") {
|
|
22
|
+
depth -= 1;
|
|
23
|
+
}
|
|
24
|
+
cursor += 1;
|
|
25
|
+
}
|
|
26
|
+
const closeBraceIndex = depth === 0 ? cursor - 1 : text.length - 1;
|
|
27
|
+
const body = text.slice(openBraceIndex + 1, closeBraceIndex);
|
|
28
|
+
const scopeText = `${header} ${body}`.trim();
|
|
29
|
+
if (areaId.length > 0) {
|
|
30
|
+
segments.push({ areaId, text: scopeText, range });
|
|
31
|
+
consumedRanges.push({
|
|
32
|
+
start: matched.index ?? 0,
|
|
33
|
+
end: closeBraceIndex + 1,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
blockPattern.lastIndex = Math.max(closeBraceIndex + 1, blockPattern.lastIndex);
|
|
37
|
+
matched = blockPattern.exec(text);
|
|
38
|
+
}
|
|
39
|
+
const inlinePattern = /\barea\s+([^\s{;]+)\s+([^{};\n]+)\s*;?/gi;
|
|
40
|
+
let inline = inlinePattern.exec(text);
|
|
41
|
+
while (inline) {
|
|
42
|
+
const start = inline.index ?? 0;
|
|
43
|
+
const insideBlock = consumedRanges.some((item) => start >= item.start && start < item.end);
|
|
44
|
+
if (!insideBlock) {
|
|
45
|
+
const areaId = normalizeAreaId(inline[1] ?? "");
|
|
46
|
+
const inlineText = (inline[2] ?? "").trim();
|
|
47
|
+
if (areaId.length > 0) {
|
|
48
|
+
segments.push({ areaId, text: inlineText, range });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
inline = inlinePattern.exec(text);
|
|
52
|
+
}
|
|
53
|
+
return segments;
|
|
54
|
+
};
|
|
55
|
+
const collectAreas = (entries) => {
|
|
56
|
+
const areas = [];
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
areas.push(...parseAreaSegments(entry.text, entry.range));
|
|
59
|
+
}
|
|
60
|
+
return areas;
|
|
61
|
+
};
|
|
62
|
+
const ospfMissingAreaRule = ({ parsed }) => {
|
|
63
|
+
const diagnostics = [];
|
|
64
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
65
|
+
if (!isProtocolType(declaration, "ospf")) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const areas = collectAreas(protocolOtherTextEntries(declaration));
|
|
69
|
+
if (areas.length > 0) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
diagnostics.push(createProtocolDiagnostic("ospf/missing-area", `OSPF protocol '${declaration.name}' has no configured areas`, declaration));
|
|
73
|
+
}
|
|
74
|
+
return diagnostics;
|
|
75
|
+
};
|
|
76
|
+
const ospfBackboneStubRule = ({ parsed }) => {
|
|
77
|
+
const diagnostics = [];
|
|
78
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
79
|
+
if (!isProtocolType(declaration, "ospf")) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const areas = collectAreas(protocolOtherTextEntries(declaration));
|
|
83
|
+
for (const area of areas) {
|
|
84
|
+
if (!isBackboneArea(area.areaId) || !/\bstub\b/i.test(area.text)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
diagnostics.push(createRuleDiagnostic("ospf/backbone-stub", `OSPF protocol '${declaration.name}' configures backbone area as stub`, area.range));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return diagnostics;
|
|
91
|
+
};
|
|
92
|
+
const ospfVlinkInBackboneRule = ({ parsed }) => {
|
|
93
|
+
const diagnostics = [];
|
|
94
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
95
|
+
if (!isProtocolType(declaration, "ospf")) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const areas = collectAreas(protocolOtherTextEntries(declaration));
|
|
99
|
+
for (const area of areas) {
|
|
100
|
+
if (!isBackboneArea(area.areaId) || !/\bvlink\b/i.test(area.text)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
diagnostics.push(createRuleDiagnostic("ospf/vlink-in-backbone", `OSPF protocol '${declaration.name}' cannot configure vlink in backbone area`, area.range));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return diagnostics;
|
|
107
|
+
};
|
|
108
|
+
const ospfAsbrStubAreaRule = ({ parsed }) => {
|
|
109
|
+
const diagnostics = [];
|
|
110
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
111
|
+
if (!isProtocolType(declaration, "ospf")) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const areas = collectAreas(protocolOtherTextEntries(declaration));
|
|
115
|
+
for (const area of areas) {
|
|
116
|
+
if (isBackboneArea(area.areaId)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (!/\bstub\b/i.test(area.text) || !/\basbr\b/i.test(area.text)) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
diagnostics.push(createRuleDiagnostic("ospf/asbr-stub-area", `OSPF protocol '${declaration.name}' declares ASBR inside stub area ${area.areaId}`, area.range));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return diagnostics;
|
|
126
|
+
};
|
|
127
|
+
export const ospfRules = [
|
|
128
|
+
ospfMissingAreaRule,
|
|
129
|
+
ospfBackboneStubRule,
|
|
130
|
+
ospfVlinkInBackboneRule,
|
|
131
|
+
ospfAsbrStubAreaRule,
|
|
132
|
+
];
|
|
133
|
+
export const collectOspfRuleDiagnostics = (context) => {
|
|
134
|
+
return ospfRules.flatMap((rule) => rule(context));
|
|
135
|
+
};
|
|
136
|
+
//# sourceMappingURL=ospf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ospf.js","sourceRoot":"","sources":["../../src/rules/ospf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { BirdDiagnostic, BirdDiagnosticSeverity, CoreSnapshot } from "@birdcc/core";
|
|
2
|
+
import type { BirdDeclaration, FilterBodyStatement, FilterDeclaration, FunctionDeclaration, ParsedBirdDocument, ProtocolDeclaration, ProtocolStatement, SourceRange, TableDeclaration, TemplateDeclaration } from "@birdcc/parser";
|
|
3
|
+
import { type RuleCode } from "./catalog.js";
|
|
4
|
+
export interface RuleContext {
|
|
5
|
+
text: string;
|
|
6
|
+
parsed: ParsedBirdDocument;
|
|
7
|
+
core: CoreSnapshot;
|
|
8
|
+
}
|
|
9
|
+
export type BirdRule = (context: RuleContext) => BirdDiagnostic[];
|
|
10
|
+
export declare const normalizeClause: (text: string) => string;
|
|
11
|
+
export declare const createRuleDiagnostic: (code: RuleCode, message: string, range: SourceRange, source?: BirdDiagnostic["source"]) => BirdDiagnostic;
|
|
12
|
+
export declare const diagnosticDedupKey: (diagnostic: BirdDiagnostic) => string;
|
|
13
|
+
export declare const pushUniqueDiagnostic: (diagnostics: BirdDiagnostic[], seen: Set<string>, diagnostic: BirdDiagnostic) => void;
|
|
14
|
+
export declare const withSeverity: (code: RuleCode, diagnostic: Omit<BirdDiagnostic, "severity" | "code">) => BirdDiagnostic;
|
|
15
|
+
export declare const protocolDeclarations: (parsed: ParsedBirdDocument) => ProtocolDeclaration[];
|
|
16
|
+
export declare const templateDeclarations: (parsed: ParsedBirdDocument) => TemplateDeclaration[];
|
|
17
|
+
export declare const tableDeclarations: (parsed: ParsedBirdDocument) => TableDeclaration[];
|
|
18
|
+
export declare const filterDeclarations: (parsed: ParsedBirdDocument) => FilterDeclaration[];
|
|
19
|
+
export declare const functionDeclarations: (parsed: ParsedBirdDocument) => FunctionDeclaration[];
|
|
20
|
+
export declare const filterAndFunctionDeclarations: (parsed: ParsedBirdDocument) => Array<FilterDeclaration | FunctionDeclaration>;
|
|
21
|
+
export declare const routerIdDeclarations: (parsed: ParsedBirdDocument) => BirdDeclaration[];
|
|
22
|
+
export declare const isProtocolType: (declaration: ProtocolDeclaration, expected: string) => boolean;
|
|
23
|
+
export declare const protocolOtherStatements: (declaration: ProtocolDeclaration) => ProtocolStatement[];
|
|
24
|
+
export declare const protocolOtherTextEntries: (declaration: ProtocolDeclaration) => Array<{
|
|
25
|
+
text: string;
|
|
26
|
+
range: SourceRange;
|
|
27
|
+
}>;
|
|
28
|
+
export declare const channelOtherEntries: (declaration: ProtocolDeclaration) => Array<{
|
|
29
|
+
channelType: string;
|
|
30
|
+
text: string;
|
|
31
|
+
range: SourceRange;
|
|
32
|
+
}>;
|
|
33
|
+
export declare const numericValue: (value: string | undefined) => number | null;
|
|
34
|
+
export declare const extractFirstNumberAfterKeyword: (text: string, keyword: string) => number | null;
|
|
35
|
+
export declare const hasBooleanValue: (value: string) => boolean;
|
|
36
|
+
export declare const extractFunctionCalls: (text: string) => string[];
|
|
37
|
+
export declare const scalarTypeOfExpression: (expressionText: string) => "int" | "bool" | "string" | "ip" | "prefix" | "unknown";
|
|
38
|
+
export declare const isPrefixLiteral: (value: string) => boolean;
|
|
39
|
+
export declare const eachFilterBodyExpression: (parsed: ParsedBirdDocument) => Array<{
|
|
40
|
+
statement: FilterBodyStatement;
|
|
41
|
+
declarationName: string;
|
|
42
|
+
}>;
|
|
43
|
+
export declare const findTemplateByName: (parsed: ParsedBirdDocument, templateName: string) => TemplateDeclaration | undefined;
|
|
44
|
+
export declare const hasSymbolKind: (core: CoreSnapshot, kind: "protocol" | "template" | "filter" | "function" | "table", name: string) => boolean;
|
|
45
|
+
export declare const createProtocolDiagnostic: (code: RuleCode, message: string, declaration: ProtocolDeclaration, severity?: BirdDiagnosticSeverity) => BirdDiagnostic;
|
|
46
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/rules/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
|
+
import { RULE_SEVERITY } from "./catalog.js";
|
|
3
|
+
export const normalizeClause = (text) => text.trim().replace(/\s+/g, " ").toLowerCase();
|
|
4
|
+
export const createRuleDiagnostic = (code, message, range, source = "linter") => ({
|
|
5
|
+
code,
|
|
6
|
+
message,
|
|
7
|
+
severity: RULE_SEVERITY[code],
|
|
8
|
+
source,
|
|
9
|
+
range: {
|
|
10
|
+
line: range.line,
|
|
11
|
+
column: range.column,
|
|
12
|
+
endLine: range.endLine,
|
|
13
|
+
endColumn: range.endColumn,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
export const diagnosticDedupKey = (diagnostic) => [
|
|
17
|
+
diagnostic.code,
|
|
18
|
+
diagnostic.message,
|
|
19
|
+
diagnostic.range.line,
|
|
20
|
+
diagnostic.range.column,
|
|
21
|
+
diagnostic.range.endLine,
|
|
22
|
+
diagnostic.range.endColumn,
|
|
23
|
+
].join(":");
|
|
24
|
+
export const pushUniqueDiagnostic = (diagnostics, seen, diagnostic) => {
|
|
25
|
+
const key = diagnosticDedupKey(diagnostic);
|
|
26
|
+
if (seen.has(key)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
seen.add(key);
|
|
30
|
+
diagnostics.push(diagnostic);
|
|
31
|
+
};
|
|
32
|
+
export const withSeverity = (code, diagnostic) => ({
|
|
33
|
+
...diagnostic,
|
|
34
|
+
code,
|
|
35
|
+
severity: RULE_SEVERITY[code],
|
|
36
|
+
});
|
|
37
|
+
export const protocolDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "protocol");
|
|
38
|
+
export const templateDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "template");
|
|
39
|
+
export const tableDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "table");
|
|
40
|
+
export const filterDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "filter");
|
|
41
|
+
export const functionDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "function");
|
|
42
|
+
export const filterAndFunctionDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "filter" || declaration.kind === "function");
|
|
43
|
+
export const routerIdDeclarations = (parsed) => parsed.program.declarations.filter((declaration) => declaration.kind === "router-id");
|
|
44
|
+
export const isProtocolType = (declaration, expected) => declaration.protocolType.toLowerCase() === expected;
|
|
45
|
+
export const protocolOtherStatements = (declaration) => declaration.statements.filter((statement) => statement.kind === "other");
|
|
46
|
+
export const protocolOtherTextEntries = (declaration) => {
|
|
47
|
+
const entries = [];
|
|
48
|
+
for (const statement of declaration.statements) {
|
|
49
|
+
if (statement.kind === "other") {
|
|
50
|
+
entries.push({ text: statement.text, range: statement });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (statement.kind !== "channel") {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
for (const entry of statement.entries) {
|
|
57
|
+
if (entry.kind !== "other") {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
entries.push({ text: entry.text, range: entry });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return entries;
|
|
64
|
+
};
|
|
65
|
+
export const channelOtherEntries = (declaration) => {
|
|
66
|
+
const entries = [];
|
|
67
|
+
for (const statement of declaration.statements) {
|
|
68
|
+
if (statement.kind !== "channel") {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
for (const entry of statement.entries) {
|
|
72
|
+
if (entry.kind !== "other") {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
entries.push({
|
|
76
|
+
channelType: statement.channelType,
|
|
77
|
+
text: entry.text,
|
|
78
|
+
range: entry,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return entries;
|
|
83
|
+
};
|
|
84
|
+
export const numericValue = (value) => {
|
|
85
|
+
if (!value) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const normalized = value.trim();
|
|
89
|
+
if (!/^-?\d+$/.test(normalized)) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const parsed = Number.parseInt(normalized, 10);
|
|
93
|
+
return Number.isNaN(parsed) ? null : parsed;
|
|
94
|
+
};
|
|
95
|
+
export const extractFirstNumberAfterKeyword = (text, keyword) => {
|
|
96
|
+
const pattern = new RegExp(`${keyword}\\s+(-?\\d+)`, "i");
|
|
97
|
+
const matched = text.match(pattern);
|
|
98
|
+
return numericValue(matched?.[1]);
|
|
99
|
+
};
|
|
100
|
+
export const hasBooleanValue = (value) => ["on", "off", "yes", "no", "true", "false", "enabled", "disabled"].includes(normalizeClause(value));
|
|
101
|
+
export const extractFunctionCalls = (text) => {
|
|
102
|
+
const names = [];
|
|
103
|
+
const pattern = /\b([A-Za-z_][A-Za-z0-9_]*)\s*\(/g;
|
|
104
|
+
const ignored = new Set(["if", "switch", "print", "defined"]);
|
|
105
|
+
let current = pattern.exec(text);
|
|
106
|
+
while (current) {
|
|
107
|
+
const name = current[1] ?? "";
|
|
108
|
+
const matchIndex = current.index ?? -1;
|
|
109
|
+
const isMethodCall = matchIndex > 0 && text[matchIndex - 1] === ".";
|
|
110
|
+
if (name.length > 0 && !ignored.has(name.toLowerCase()) && !isMethodCall) {
|
|
111
|
+
names.push(name);
|
|
112
|
+
}
|
|
113
|
+
current = pattern.exec(text);
|
|
114
|
+
}
|
|
115
|
+
return names;
|
|
116
|
+
};
|
|
117
|
+
export const scalarTypeOfExpression = (expressionText) => {
|
|
118
|
+
const text = expressionText.trim();
|
|
119
|
+
if (/^-?\d+$/.test(text)) {
|
|
120
|
+
return "int";
|
|
121
|
+
}
|
|
122
|
+
if (/^(true|false|yes|no|on|off)$/i.test(text)) {
|
|
123
|
+
return "bool";
|
|
124
|
+
}
|
|
125
|
+
if ((text.startsWith('"') && text.endsWith('"')) ||
|
|
126
|
+
(text.startsWith("'") && text.endsWith("'"))) {
|
|
127
|
+
return "string";
|
|
128
|
+
}
|
|
129
|
+
if (text.includes("/") && isPrefixLiteral(text)) {
|
|
130
|
+
return "prefix";
|
|
131
|
+
}
|
|
132
|
+
if (isIP(text) !== 0) {
|
|
133
|
+
return "ip";
|
|
134
|
+
}
|
|
135
|
+
return "unknown";
|
|
136
|
+
};
|
|
137
|
+
export const isPrefixLiteral = (value) => {
|
|
138
|
+
const [address, lengthText] = value.split("/");
|
|
139
|
+
if (!address || !lengthText) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const length = numericValue(lengthText);
|
|
143
|
+
if (length === null || length < 0 || length > 128) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
const family = isIP(address.trim());
|
|
147
|
+
if (family === 4) {
|
|
148
|
+
return length <= 32;
|
|
149
|
+
}
|
|
150
|
+
if (family === 6) {
|
|
151
|
+
return length <= 128;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
};
|
|
155
|
+
export const eachFilterBodyExpression = (parsed) => {
|
|
156
|
+
const list = [];
|
|
157
|
+
for (const declaration of filterAndFunctionDeclarations(parsed)) {
|
|
158
|
+
for (const statement of declaration.statements) {
|
|
159
|
+
list.push({ statement, declarationName: declaration.name });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return list;
|
|
163
|
+
};
|
|
164
|
+
export const findTemplateByName = (parsed, templateName) => {
|
|
165
|
+
const lowered = templateName.toLowerCase();
|
|
166
|
+
return templateDeclarations(parsed).find((item) => item.name.toLowerCase() === lowered);
|
|
167
|
+
};
|
|
168
|
+
export const hasSymbolKind = (core, kind, name) => {
|
|
169
|
+
const lowered = name.toLowerCase();
|
|
170
|
+
return core.symbols.some((symbol) => symbol.kind === kind && symbol.name.toLowerCase() === lowered);
|
|
171
|
+
};
|
|
172
|
+
export const createProtocolDiagnostic = (code, message, declaration, severity) => ({
|
|
173
|
+
code,
|
|
174
|
+
message,
|
|
175
|
+
severity: severity ?? RULE_SEVERITY[code],
|
|
176
|
+
source: "linter",
|
|
177
|
+
range: {
|
|
178
|
+
line: declaration.nameRange.line,
|
|
179
|
+
column: declaration.nameRange.column,
|
|
180
|
+
endLine: declaration.nameRange.endLine,
|
|
181
|
+
endColumn: declaration.nameRange.endColumn,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/rules/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BirdDiagnostic } from "@birdcc/core";
|
|
2
|
+
import { type BirdRule } from "./shared.js";
|
|
3
|
+
export declare const symRules: BirdRule[];
|
|
4
|
+
export declare const collectSymRuleDiagnostics: (context: Parameters<BirdRule>[0]) => BirdDiagnostic[];
|
|
5
|
+
//# sourceMappingURL=sym.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sym.d.ts","sourceRoot":"","sources":["../../src/rules/sym.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,OAAO,EAYL,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAqTrB,eAAO,MAAM,QAAQ,EAAE,QAAQ,EAK9B,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,SAAS,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAC/B,cAAc,EAEhB,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { createRuleDiagnostic, eachFilterBodyExpression, extractFunctionCalls, filterDeclarations, findTemplateByName, functionDeclarations, hasSymbolKind, normalizeClause, pushUniqueDiagnostic, protocolDeclarations, tableDeclarations, } from "./shared.js";
|
|
2
|
+
const normalizeProtocolFamily = (text) => normalizeClause(text).split(" ")[0] ?? "";
|
|
3
|
+
const BUILTIN_FILTER_NAMES = new Set([
|
|
4
|
+
"all",
|
|
5
|
+
"none",
|
|
6
|
+
"accept",
|
|
7
|
+
"reject",
|
|
8
|
+
"announce",
|
|
9
|
+
]);
|
|
10
|
+
const BUILTIN_FUNCTION_NAMES = new Set([
|
|
11
|
+
"net",
|
|
12
|
+
"bgp_path",
|
|
13
|
+
"bgp_community",
|
|
14
|
+
"bgp_ext_community",
|
|
15
|
+
"bgp_large_community",
|
|
16
|
+
"bgp_origin",
|
|
17
|
+
"defined",
|
|
18
|
+
"len",
|
|
19
|
+
"match",
|
|
20
|
+
"route_source",
|
|
21
|
+
"roa_check",
|
|
22
|
+
"prefix",
|
|
23
|
+
"ip",
|
|
24
|
+
"int",
|
|
25
|
+
]);
|
|
26
|
+
const isImportOrExportFilterClause = (value) => {
|
|
27
|
+
if (!value || typeof value !== "object") {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return value.mode === "filter";
|
|
31
|
+
};
|
|
32
|
+
const isChannelFilterClause = (entry) => (entry.kind === "import" || entry.kind === "export") &&
|
|
33
|
+
entry.mode === "filter";
|
|
34
|
+
const collectProtocolFilterClauses = (declaration) => {
|
|
35
|
+
const clauses = [];
|
|
36
|
+
for (const statement of declaration.statements) {
|
|
37
|
+
if (isImportOrExportFilterClause(statement)) {
|
|
38
|
+
clauses.push({
|
|
39
|
+
filterName: statement.filterName,
|
|
40
|
+
range: statement.filterNameRange ?? statement,
|
|
41
|
+
});
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (statement.kind !== "channel") {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
for (const entry of statement.entries) {
|
|
48
|
+
if (!isChannelFilterClause(entry)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
clauses.push({
|
|
52
|
+
filterName: entry.filterName,
|
|
53
|
+
range: entry.filterNameRange ?? entry,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return clauses;
|
|
58
|
+
};
|
|
59
|
+
const symProtoTypeMismatchRule = ({ parsed }) => {
|
|
60
|
+
const diagnostics = [];
|
|
61
|
+
const seen = new Set();
|
|
62
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
63
|
+
if (!declaration.fromTemplate) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const template = findTemplateByName(parsed, declaration.fromTemplate);
|
|
67
|
+
if (!template) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const protocolFamily = normalizeProtocolFamily(declaration.protocolType);
|
|
71
|
+
const templateFamily = normalizeProtocolFamily(template.templateType);
|
|
72
|
+
if (protocolFamily.length === 0 ||
|
|
73
|
+
templateFamily.length === 0 ||
|
|
74
|
+
protocolFamily === templateFamily) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/proto-type-mismatch", `Protocol '${declaration.name}' (${declaration.protocolType}) cannot use template '${template.name}' (${template.templateType})`, declaration.fromTemplateRange ?? declaration.nameRange));
|
|
78
|
+
}
|
|
79
|
+
return diagnostics;
|
|
80
|
+
};
|
|
81
|
+
const symFilterRequiredRule = ({ parsed, core }) => {
|
|
82
|
+
const diagnostics = [];
|
|
83
|
+
const seen = new Set();
|
|
84
|
+
const filterNames = new Set(filterDeclarations(parsed).map((item) => item.name.toLowerCase()));
|
|
85
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
86
|
+
for (const clause of collectProtocolFilterClauses(declaration)) {
|
|
87
|
+
const name = clause.filterName?.trim();
|
|
88
|
+
if (!name) {
|
|
89
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/filter-required", `Protocol '${declaration.name}' requires a filter name in import/export filter clause`, clause.range));
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const loweredName = name.toLowerCase();
|
|
93
|
+
if (!filterNames.has(loweredName) &&
|
|
94
|
+
!hasSymbolKind(core, "filter", name)) {
|
|
95
|
+
if (BUILTIN_FILTER_NAMES.has(loweredName)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/filter-required", `Protocol '${declaration.name}' references unknown filter '${name}'`, clause.range));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return diagnostics;
|
|
103
|
+
};
|
|
104
|
+
const symFunctionRequiredRule = ({ parsed, core }) => {
|
|
105
|
+
const diagnostics = [];
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
const functions = new Set(functionDeclarations(parsed).map((item) => item.name.toLowerCase()));
|
|
108
|
+
for (const builtin of BUILTIN_FUNCTION_NAMES) {
|
|
109
|
+
functions.add(builtin);
|
|
110
|
+
}
|
|
111
|
+
for (const { statement, declarationName } of eachFilterBodyExpression(parsed)) {
|
|
112
|
+
const textParts = [];
|
|
113
|
+
if (statement.kind === "expression") {
|
|
114
|
+
textParts.push(statement.expressionText);
|
|
115
|
+
}
|
|
116
|
+
if (statement.kind === "other") {
|
|
117
|
+
textParts.push(statement.text);
|
|
118
|
+
}
|
|
119
|
+
if (statement.kind === "if" && statement.conditionText) {
|
|
120
|
+
textParts.push(statement.conditionText);
|
|
121
|
+
}
|
|
122
|
+
if (textParts.length === 0) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const joined = textParts.join(" ");
|
|
126
|
+
for (const callName of extractFunctionCalls(joined)) {
|
|
127
|
+
if (functions.has(callName.toLowerCase()) ||
|
|
128
|
+
hasSymbolKind(core, "function", callName)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/function-required", `Declaration '${declarationName}' references undefined function '${callName}'`, statement));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return diagnostics;
|
|
135
|
+
};
|
|
136
|
+
const symTableRequiredRule = ({ parsed, core }) => {
|
|
137
|
+
const diagnostics = [];
|
|
138
|
+
const seen = new Set();
|
|
139
|
+
const tableNames = new Set(tableDeclarations(parsed).map((item) => item.name.toLowerCase()));
|
|
140
|
+
for (const declaration of protocolDeclarations(parsed)) {
|
|
141
|
+
for (const statement of declaration.statements) {
|
|
142
|
+
if (statement.kind === "channel") {
|
|
143
|
+
for (const entry of statement.entries) {
|
|
144
|
+
if (entry.kind !== "table") {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const tableName = entry.tableName.trim();
|
|
148
|
+
if (!tableName) {
|
|
149
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/table-required", `Protocol '${declaration.name}' requires a table name in channel table clause`, entry));
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (!tableNames.has(tableName.toLowerCase()) &&
|
|
153
|
+
!hasSymbolKind(core, "table", tableName)) {
|
|
154
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/table-required", `Protocol '${declaration.name}' references unknown table '${tableName}'`, entry.tableNameRange));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (statement.kind !== "other") {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const text = statement.text;
|
|
162
|
+
const matched = text.match(/\btable\b(?:\s+([A-Za-z_][A-Za-z0-9_]*))?/i);
|
|
163
|
+
if (!matched) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const tableName = matched[1]?.trim();
|
|
167
|
+
if (!tableName) {
|
|
168
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/table-required", `Protocol '${declaration.name}' requires table name after 'table'`, statement));
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (!tableNames.has(tableName.toLowerCase()) &&
|
|
172
|
+
!hasSymbolKind(core, "table", tableName)) {
|
|
173
|
+
pushUniqueDiagnostic(diagnostics, seen, createRuleDiagnostic("sym/table-required", `Protocol '${declaration.name}' references unknown table '${tableName}'`, statement));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return diagnostics;
|
|
178
|
+
};
|
|
179
|
+
export const symRules = [
|
|
180
|
+
symProtoTypeMismatchRule,
|
|
181
|
+
symFilterRequiredRule,
|
|
182
|
+
symFunctionRequiredRule,
|
|
183
|
+
symTableRequiredRule,
|
|
184
|
+
];
|
|
185
|
+
export const collectSymRuleDiagnostics = (context) => {
|
|
186
|
+
return symRules.flatMap((rule) => rule(context));
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=sym.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sym.js","sourceRoot":"","sources":["../../src/rules/sym.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BirdDiagnostic } from "@birdcc/core";
|
|
2
|
+
import { type BirdRule } from "./shared.js";
|
|
3
|
+
export declare const typeRules: BirdRule[];
|
|
4
|
+
export declare const collectTypeRuleDiagnostics: (context: Parameters<BirdRule>[0]) => BirdDiagnostic[];
|
|
5
|
+
//# sourceMappingURL=type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../src/rules/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAgMrB,eAAO,MAAM,SAAS,EAAE,QAAQ,EAG/B,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,SAAS,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAC/B,cAAc,EAEhB,CAAC"}
|