@jrc03c/gtlint 0.12.1
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/LICENSE +21 -0
- package/README.md +235 -0
- package/bin/gtlint.js +4 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +248 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +32 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +112 -0
- package/dist/config.js.map +1 -0
- package/dist/formatter/formatter.d.ts +22 -0
- package/dist/formatter/formatter.d.ts.map +1 -0
- package/dist/formatter/formatter.js +376 -0
- package/dist/formatter/formatter.js.map +1 -0
- package/dist/formatter/index.d.ts +2 -0
- package/dist/formatter/index.d.ts.map +1 -0
- package/dist/formatter/index.js +2 -0
- package/dist/formatter/index.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/language/index.d.ts +8 -0
- package/dist/language/index.d.ts.map +1 -0
- package/dist/language/index.js +8 -0
- package/dist/language/index.js.map +1 -0
- package/dist/language/keyword-spec.d.ts +87 -0
- package/dist/language/keyword-spec.d.ts.map +1 -0
- package/dist/language/keyword-spec.js +772 -0
- package/dist/language/keyword-spec.js.map +1 -0
- package/dist/lexer/index.d.ts +3 -0
- package/dist/lexer/index.d.ts.map +1 -0
- package/dist/lexer/index.js +3 -0
- package/dist/lexer/index.js.map +1 -0
- package/dist/lexer/lexer.d.ts +36 -0
- package/dist/lexer/lexer.d.ts.map +1 -0
- package/dist/lexer/lexer.js +709 -0
- package/dist/lexer/lexer.js.map +1 -0
- package/dist/lexer/tokens.d.ts +45 -0
- package/dist/lexer/tokens.d.ts.map +1 -0
- package/dist/lexer/tokens.js +170 -0
- package/dist/lexer/tokens.js.map +1 -0
- package/dist/linter/directives.d.ts +71 -0
- package/dist/linter/directives.d.ts.map +1 -0
- package/dist/linter/directives.js +329 -0
- package/dist/linter/directives.js.map +1 -0
- package/dist/linter/index.d.ts +6 -0
- package/dist/linter/index.d.ts.map +1 -0
- package/dist/linter/index.js +4 -0
- package/dist/linter/index.js.map +1 -0
- package/dist/linter/linter.d.ts +39 -0
- package/dist/linter/linter.d.ts.map +1 -0
- package/dist/linter/linter.js +292 -0
- package/dist/linter/linter.js.map +1 -0
- package/dist/linter/rules/correct-indentation.d.ts +22 -0
- package/dist/linter/rules/correct-indentation.d.ts.map +1 -0
- package/dist/linter/rules/correct-indentation.js +111 -0
- package/dist/linter/rules/correct-indentation.js.map +1 -0
- package/dist/linter/rules/goto-needs-reset-in-events.d.ts +28 -0
- package/dist/linter/rules/goto-needs-reset-in-events.d.ts.map +1 -0
- package/dist/linter/rules/goto-needs-reset-in-events.js +88 -0
- package/dist/linter/rules/goto-needs-reset-in-events.js.map +1 -0
- package/dist/linter/rules/indent-style.d.ts +3 -0
- package/dist/linter/rules/indent-style.d.ts.map +1 -0
- package/dist/linter/rules/indent-style.js +41 -0
- package/dist/linter/rules/indent-style.js.map +1 -0
- package/dist/linter/rules/index.d.ts +5 -0
- package/dist/linter/rules/index.d.ts.map +1 -0
- package/dist/linter/rules/index.js +47 -0
- package/dist/linter/rules/index.js.map +1 -0
- package/dist/linter/rules/no-duplicate-labels.d.ts +3 -0
- package/dist/linter/rules/no-duplicate-labels.d.ts.map +1 -0
- package/dist/linter/rules/no-duplicate-labels.js +75 -0
- package/dist/linter/rules/no-duplicate-labels.js.map +1 -0
- package/dist/linter/rules/no-empty-blocks.d.ts +15 -0
- package/dist/linter/rules/no-empty-blocks.d.ts.map +1 -0
- package/dist/linter/rules/no-empty-blocks.js +45 -0
- package/dist/linter/rules/no-empty-blocks.js.map +1 -0
- package/dist/linter/rules/no-inline-argument.d.ts +14 -0
- package/dist/linter/rules/no-inline-argument.d.ts.map +1 -0
- package/dist/linter/rules/no-inline-argument.js +56 -0
- package/dist/linter/rules/no-inline-argument.js.map +1 -0
- package/dist/linter/rules/no-invalid-goto.d.ts +3 -0
- package/dist/linter/rules/no-invalid-goto.d.ts.map +1 -0
- package/dist/linter/rules/no-invalid-goto.js +92 -0
- package/dist/linter/rules/no-invalid-goto.js.map +1 -0
- package/dist/linter/rules/no-single-quotes.d.ts +3 -0
- package/dist/linter/rules/no-single-quotes.d.ts.map +1 -0
- package/dist/linter/rules/no-single-quotes.js +73 -0
- package/dist/linter/rules/no-single-quotes.js.map +1 -0
- package/dist/linter/rules/no-unclosed-bracket.d.ts +3 -0
- package/dist/linter/rules/no-unclosed-bracket.d.ts.map +1 -0
- package/dist/linter/rules/no-unclosed-bracket.js +108 -0
- package/dist/linter/rules/no-unclosed-bracket.js.map +1 -0
- package/dist/linter/rules/no-unclosed-string.d.ts +3 -0
- package/dist/linter/rules/no-unclosed-string.d.ts.map +1 -0
- package/dist/linter/rules/no-unclosed-string.js +48 -0
- package/dist/linter/rules/no-unclosed-string.js.map +1 -0
- package/dist/linter/rules/no-undefined-vars.d.ts +3 -0
- package/dist/linter/rules/no-undefined-vars.d.ts.map +1 -0
- package/dist/linter/rules/no-undefined-vars.js +257 -0
- package/dist/linter/rules/no-undefined-vars.js.map +1 -0
- package/dist/linter/rules/no-unreachable-code.d.ts +3 -0
- package/dist/linter/rules/no-unreachable-code.d.ts.map +1 -0
- package/dist/linter/rules/no-unreachable-code.js +215 -0
- package/dist/linter/rules/no-unreachable-code.js.map +1 -0
- package/dist/linter/rules/no-unused-labels.d.ts +3 -0
- package/dist/linter/rules/no-unused-labels.d.ts.map +1 -0
- package/dist/linter/rules/no-unused-labels.js +77 -0
- package/dist/linter/rules/no-unused-labels.js.map +1 -0
- package/dist/linter/rules/no-unused-vars.d.ts +3 -0
- package/dist/linter/rules/no-unused-vars.d.ts.map +1 -0
- package/dist/linter/rules/no-unused-vars.js +288 -0
- package/dist/linter/rules/no-unused-vars.js.map +1 -0
- package/dist/linter/rules/purchase-subkeyword-constraints.d.ts +15 -0
- package/dist/linter/rules/purchase-subkeyword-constraints.d.ts.map +1 -0
- package/dist/linter/rules/purchase-subkeyword-constraints.js +88 -0
- package/dist/linter/rules/purchase-subkeyword-constraints.js.map +1 -0
- package/dist/linter/rules/required-subkeywords.d.ts +14 -0
- package/dist/linter/rules/required-subkeywords.d.ts.map +1 -0
- package/dist/linter/rules/required-subkeywords.js +64 -0
- package/dist/linter/rules/required-subkeywords.js.map +1 -0
- package/dist/linter/rules/valid-keyword.d.ts +3 -0
- package/dist/linter/rules/valid-keyword.d.ts.map +1 -0
- package/dist/linter/rules/valid-keyword.js +41 -0
- package/dist/linter/rules/valid-keyword.js.map +1 -0
- package/dist/linter/rules/valid-sub-keyword.d.ts +3 -0
- package/dist/linter/rules/valid-sub-keyword.d.ts.map +1 -0
- package/dist/linter/rules/valid-sub-keyword.js +89 -0
- package/dist/linter/rules/valid-sub-keyword.js.map +1 -0
- package/dist/linter/rules/valid-subkeyword-value.d.ts +16 -0
- package/dist/linter/rules/valid-subkeyword-value.d.ts.map +1 -0
- package/dist/linter/rules/valid-subkeyword-value.js +100 -0
- package/dist/linter/rules/valid-subkeyword-value.js.map +1 -0
- package/dist/parser/ast.d.ts +119 -0
- package/dist/parser/ast.d.ts.map +1 -0
- package/dist/parser/ast.js +58 -0
- package/dist/parser/ast.js.map +1 -0
- package/dist/parser/index.d.ts +3 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +3 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/parser.d.ts +55 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +608 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +36 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { noUndefinedVars } from './no-undefined-vars.js';
|
|
2
|
+
import { noUnusedVars } from './no-unused-vars.js';
|
|
3
|
+
import { validKeyword } from './valid-keyword.js';
|
|
4
|
+
import { validSubKeyword } from './valid-sub-keyword.js';
|
|
5
|
+
import { noInvalidGoto } from './no-invalid-goto.js';
|
|
6
|
+
import { indentStyle } from './indent-style.js';
|
|
7
|
+
import { noUnclosedString } from './no-unclosed-string.js';
|
|
8
|
+
import { noUnclosedBracket } from './no-unclosed-bracket.js';
|
|
9
|
+
import { noSingleQuotes } from './no-single-quotes.js';
|
|
10
|
+
import { noUnreachableCode } from './no-unreachable-code.js';
|
|
11
|
+
import { requiredSubkeywords } from './required-subkeywords.js';
|
|
12
|
+
import { validSubkeywordValue } from './valid-subkeyword-value.js';
|
|
13
|
+
import { noInlineArgument } from './no-inline-argument.js';
|
|
14
|
+
import { gotoNeedsResetInEvents } from './goto-needs-reset-in-events.js';
|
|
15
|
+
import { purchaseSubkeywordConstraints } from './purchase-subkeyword-constraints.js';
|
|
16
|
+
import { correctIndentation } from './correct-indentation.js';
|
|
17
|
+
import { noDuplicateLabels } from './no-duplicate-labels.js';
|
|
18
|
+
import { noUnusedLabels } from './no-unused-labels.js';
|
|
19
|
+
import { noEmptyBlocks } from './no-empty-blocks.js';
|
|
20
|
+
export const rules = {
|
|
21
|
+
'no-undefined-vars': noUndefinedVars,
|
|
22
|
+
'no-unused-vars': noUnusedVars,
|
|
23
|
+
'valid-keyword': validKeyword,
|
|
24
|
+
'valid-sub-keyword': validSubKeyword,
|
|
25
|
+
'no-invalid-goto': noInvalidGoto,
|
|
26
|
+
'indent-style': indentStyle,
|
|
27
|
+
'no-unclosed-string': noUnclosedString,
|
|
28
|
+
'no-unclosed-bracket': noUnclosedBracket,
|
|
29
|
+
'no-single-quotes': noSingleQuotes,
|
|
30
|
+
'no-unreachable-code': noUnreachableCode,
|
|
31
|
+
'required-subkeywords': requiredSubkeywords,
|
|
32
|
+
'valid-subkeyword-value': validSubkeywordValue,
|
|
33
|
+
'no-inline-argument': noInlineArgument,
|
|
34
|
+
'goto-needs-reset-in-events': gotoNeedsResetInEvents,
|
|
35
|
+
'purchase-subkeyword-constraints': purchaseSubkeywordConstraints,
|
|
36
|
+
'correct-indentation': correctIndentation,
|
|
37
|
+
'no-duplicate-labels': noDuplicateLabels,
|
|
38
|
+
'no-unused-labels': noUnusedLabels,
|
|
39
|
+
'no-empty-blocks': noEmptyBlocks,
|
|
40
|
+
};
|
|
41
|
+
export function getRule(name) {
|
|
42
|
+
return rules[name];
|
|
43
|
+
}
|
|
44
|
+
export function getAllRules() {
|
|
45
|
+
return Object.values(rules);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/linter/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,CAAC,MAAM,KAAK,GAA6B;IAC7C,mBAAmB,EAAE,eAAe;IACpC,gBAAgB,EAAE,YAAY;IAC9B,eAAe,EAAE,YAAY;IAC7B,mBAAmB,EAAE,eAAe;IACpC,iBAAiB,EAAE,aAAa;IAChC,cAAc,EAAE,WAAW;IAC3B,oBAAoB,EAAE,gBAAgB;IACtC,qBAAqB,EAAE,iBAAiB;IACxC,kBAAkB,EAAE,cAAc;IAClC,qBAAqB,EAAE,iBAAiB;IACxC,sBAAsB,EAAE,mBAAmB;IAC3C,wBAAwB,EAAE,oBAAoB;IAC9C,oBAAoB,EAAE,gBAAgB;IACtC,4BAA4B,EAAE,sBAAsB;IACpD,iCAAiC,EAAE,6BAA6B;IAChE,qBAAqB,EAAE,kBAAkB;IACzC,qBAAqB,EAAE,iBAAiB;IACxC,kBAAkB,EAAE,cAAc;IAClC,iBAAiB,EAAE,aAAa;CACjC,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-duplicate-labels.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-duplicate-labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAG1D,eAAO,MAAM,iBAAiB,EAAE,QA6E/B,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export const noDuplicateLabels = {
|
|
2
|
+
name: 'no-duplicate-labels',
|
|
3
|
+
description: 'Disallow duplicate *label definitions',
|
|
4
|
+
severity: 'error',
|
|
5
|
+
create(context) {
|
|
6
|
+
const labelDefinitions = [];
|
|
7
|
+
function collectLabels(node) {
|
|
8
|
+
if (!node || typeof node !== 'object')
|
|
9
|
+
return;
|
|
10
|
+
if (node.type === 'Program') {
|
|
11
|
+
for (const stmt of node.body) {
|
|
12
|
+
collectLabels(stmt);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
else if (node.type === 'KeywordStatement') {
|
|
16
|
+
const kw = node;
|
|
17
|
+
if (kw.keyword === 'label' && kw.argument) {
|
|
18
|
+
let labelName = '';
|
|
19
|
+
if (kw.argument.type === 'TextContent') {
|
|
20
|
+
const text = kw.argument.parts.find(p => typeof p === 'string');
|
|
21
|
+
if (text) {
|
|
22
|
+
labelName = text.trim();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if (kw.argument.type === 'Identifier') {
|
|
26
|
+
labelName = kw.argument.name;
|
|
27
|
+
}
|
|
28
|
+
if (labelName) {
|
|
29
|
+
labelDefinitions.push({
|
|
30
|
+
name: labelName,
|
|
31
|
+
line: kw.loc.start.line,
|
|
32
|
+
column: kw.loc.start.column,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Recurse into body
|
|
37
|
+
for (const stmt of kw.body) {
|
|
38
|
+
collectLabels(stmt);
|
|
39
|
+
}
|
|
40
|
+
// Recurse into sub-keywords
|
|
41
|
+
for (const sub of kw.subKeywords) {
|
|
42
|
+
for (const stmt of sub.body) {
|
|
43
|
+
collectLabels(stmt);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (node.type === 'AnswerOption') {
|
|
48
|
+
for (const stmt of node.body) {
|
|
49
|
+
collectLabels(stmt);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
Program(node) {
|
|
55
|
+
collectLabels(node);
|
|
56
|
+
// Group labels by name and report duplicates
|
|
57
|
+
const seen = new Map();
|
|
58
|
+
for (const label of labelDefinitions) {
|
|
59
|
+
const first = seen.get(label.name);
|
|
60
|
+
if (first) {
|
|
61
|
+
context.report({
|
|
62
|
+
message: `Duplicate label '${label.name}' (first defined on line ${first.line})`,
|
|
63
|
+
line: label.line,
|
|
64
|
+
column: label.column,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
seen.set(label.name, { line: label.line, column: label.column });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=no-duplicate-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-duplicate-labels.js","sourceRoot":"","sources":["../../../src/linter/rules/no-duplicate-labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LintRule } from '../linter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rule: no-empty-blocks
|
|
4
|
+
*
|
|
5
|
+
* Detects empty control flow and body-required keyword blocks.
|
|
6
|
+
* An empty block is likely an authoring mistake where the body was left blank.
|
|
7
|
+
*
|
|
8
|
+
* Examples of violations:
|
|
9
|
+
* - `*if: x > 5` with no indented body
|
|
10
|
+
* - `*while: running` with no indented body
|
|
11
|
+
* - `*page:` with no indented body
|
|
12
|
+
* - `*else:` with no indented body
|
|
13
|
+
*/
|
|
14
|
+
export declare const noEmptyBlocks: LintRule;
|
|
15
|
+
//# sourceMappingURL=no-empty-blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-empty-blocks.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-empty-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAI1D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,EAAE,QAiC3B,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getKeywordSpec } from '../../language/keyword-spec.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rule: no-empty-blocks
|
|
4
|
+
*
|
|
5
|
+
* Detects empty control flow and body-required keyword blocks.
|
|
6
|
+
* An empty block is likely an authoring mistake where the body was left blank.
|
|
7
|
+
*
|
|
8
|
+
* Examples of violations:
|
|
9
|
+
* - `*if: x > 5` with no indented body
|
|
10
|
+
* - `*while: running` with no indented body
|
|
11
|
+
* - `*page:` with no indented body
|
|
12
|
+
* - `*else:` with no indented body
|
|
13
|
+
*/
|
|
14
|
+
export const noEmptyBlocks = {
|
|
15
|
+
name: 'no-empty-blocks',
|
|
16
|
+
description: 'Disallow empty keyword blocks',
|
|
17
|
+
severity: 'error',
|
|
18
|
+
create(context) {
|
|
19
|
+
return {
|
|
20
|
+
KeywordStatement(node) {
|
|
21
|
+
if (node.body.length > 0 || node.subKeywords.length > 0)
|
|
22
|
+
return;
|
|
23
|
+
const keyword = node.keyword.toLowerCase();
|
|
24
|
+
// else and elseif are not in KEYWORD_SPECS but should always have a body
|
|
25
|
+
if (keyword === 'else' || keyword === 'elseif') {
|
|
26
|
+
context.report({
|
|
27
|
+
message: `\`*${keyword}:\` block is empty`,
|
|
28
|
+
line: node.loc.start.line,
|
|
29
|
+
column: node.loc.start.column,
|
|
30
|
+
});
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const spec = getKeywordSpec(keyword);
|
|
34
|
+
if (spec?.body.required && node.body.length === 0) {
|
|
35
|
+
context.report({
|
|
36
|
+
message: `\`*${keyword}:\` block is empty`,
|
|
37
|
+
line: node.loc.start.line,
|
|
38
|
+
column: node.loc.start.column,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=no-empty-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-empty-blocks.js","sourceRoot":"","sources":["../../../src/linter/rules/no-empty-blocks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,aAAa,GAAa;IACrC,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,+BAA+B;IAC5C,QAAQ,EAAE,OAAO;IAEjB,MAAM,CAAC,OAAoB;QACzB,OAAO;YACL,gBAAgB,CAAC,IAAsB;gBACrC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;oBAAE,OAAO;gBAEhE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;gBAE3C,yEAAyE;gBACzE,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAC/C,OAAO,CAAC,MAAM,CAAC;wBACb,OAAO,EAAE,MAAM,OAAO,oBAAoB;wBAC1C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;wBACzB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;qBAC9B,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;gBAED,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;gBACrC,IAAI,IAAI,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAClD,OAAO,CAAC,MAAM,CAAC;wBACb,OAAO,EAAE,MAAM,OAAO,oBAAoB;wBAC1C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;wBACzB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;qBAC9B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LintRule } from '../linter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rule: no-inline-argument
|
|
4
|
+
*
|
|
5
|
+
* Ensures that keywords that shouldn't have inline arguments don't have them.
|
|
6
|
+
*
|
|
7
|
+
* Examples of violations:
|
|
8
|
+
* - `*page: something` (should be just `*page`)
|
|
9
|
+
* - `*html: something` (should be just `*html`)
|
|
10
|
+
* - `*events: something` (should be just `*events`)
|
|
11
|
+
* - `*clear: something` (should be just `*clear`)
|
|
12
|
+
*/
|
|
13
|
+
export declare const noInlineArgument: LintRule;
|
|
14
|
+
//# sourceMappingURL=no-inline-argument.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-inline-argument.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-inline-argument.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAI1D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,QA6C9B,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getKeywordSpec } from '../../language/keyword-spec.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rule: no-inline-argument
|
|
4
|
+
*
|
|
5
|
+
* Ensures that keywords that shouldn't have inline arguments don't have them.
|
|
6
|
+
*
|
|
7
|
+
* Examples of violations:
|
|
8
|
+
* - `*page: something` (should be just `*page`)
|
|
9
|
+
* - `*html: something` (should be just `*html`)
|
|
10
|
+
* - `*events: something` (should be just `*events`)
|
|
11
|
+
* - `*clear: something` (should be just `*clear`)
|
|
12
|
+
*/
|
|
13
|
+
export const noInlineArgument = {
|
|
14
|
+
name: 'no-inline-argument',
|
|
15
|
+
description: 'Ensure keywords that should not have inline arguments do not have them',
|
|
16
|
+
severity: 'error',
|
|
17
|
+
create(context) {
|
|
18
|
+
function checkKeyword(node) {
|
|
19
|
+
const keyword = node.keyword.toLowerCase();
|
|
20
|
+
const spec = getKeywordSpec(keyword);
|
|
21
|
+
if (!spec)
|
|
22
|
+
return;
|
|
23
|
+
// Check if this keyword should not have an argument
|
|
24
|
+
if (spec.argument.type === 'none' && node.argument !== null) {
|
|
25
|
+
context.report({
|
|
26
|
+
message: `'*${keyword}' should not have an inline argument`,
|
|
27
|
+
line: node.loc.start.line,
|
|
28
|
+
column: node.loc.start.column,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function visit(node) {
|
|
33
|
+
if (node.type === 'Program') {
|
|
34
|
+
for (const stmt of node.body) {
|
|
35
|
+
if (stmt.type === 'KeywordStatement') {
|
|
36
|
+
visit(stmt);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (node.type === 'KeywordStatement') {
|
|
41
|
+
checkKeyword(node);
|
|
42
|
+
for (const stmt of node.body) {
|
|
43
|
+
if (stmt.type === 'KeywordStatement') {
|
|
44
|
+
visit(stmt);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
Program(node) {
|
|
51
|
+
visit(node);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=no-inline-argument.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-inline-argument.js","sourceRoot":"","sources":["../../../src/linter/rules/no-inline-argument.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,wEAAwE;IACrF,QAAQ,EAAE,OAAO;IAEjB,MAAM,CAAC,OAAoB;QACzB,SAAS,YAAY,CAAC,IAAsB;YAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YAErC,IAAI,CAAC,IAAI;gBAAE,OAAO;YAElB,oDAAoD;YACpD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC5D,OAAO,CAAC,MAAM,CAAC;oBACb,OAAO,EAAE,KAAK,OAAO,sCAAsC;oBAC3D,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;oBACzB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;iBAC9B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,SAAS,KAAK,CAAC,IAAgC;YAC7C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;wBACrC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC5C,YAAY,CAAC,IAAI,CAAC,CAAC;gBACnB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;wBACrC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,CAAC,IAAa;gBACnB,KAAK,CAAC,IAAI,CAAC,CAAC;YACd,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-invalid-goto.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-invalid-goto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAG1D,eAAO,MAAM,aAAa,EAAE,QA8F3B,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export const noInvalidGoto = {
|
|
2
|
+
name: 'no-invalid-goto',
|
|
3
|
+
description: 'Ensure *goto targets exist',
|
|
4
|
+
severity: 'error',
|
|
5
|
+
create(context) {
|
|
6
|
+
const definedLabels = new Set();
|
|
7
|
+
const gotoStatements = [];
|
|
8
|
+
function collectLabels(node) {
|
|
9
|
+
if (!node || typeof node !== 'object')
|
|
10
|
+
return;
|
|
11
|
+
if (node.type === 'Program') {
|
|
12
|
+
for (const stmt of node.body) {
|
|
13
|
+
collectLabels(stmt);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
else if (node.type === 'KeywordStatement') {
|
|
17
|
+
const kw = node;
|
|
18
|
+
// Collect *label: definitions
|
|
19
|
+
if (kw.keyword === 'label' && kw.argument) {
|
|
20
|
+
let labelName = '';
|
|
21
|
+
if (kw.argument.type === 'TextContent') {
|
|
22
|
+
const text = kw.argument.parts.find(p => typeof p === 'string');
|
|
23
|
+
if (text) {
|
|
24
|
+
labelName = text.trim();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (kw.argument.type === 'Identifier') {
|
|
28
|
+
labelName = kw.argument.name;
|
|
29
|
+
}
|
|
30
|
+
if (labelName) {
|
|
31
|
+
definedLabels.add(labelName);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Collect *goto: usages
|
|
35
|
+
if (kw.keyword === 'goto' && kw.argument) {
|
|
36
|
+
let targetName = '';
|
|
37
|
+
if (kw.argument.type === 'TextContent') {
|
|
38
|
+
const text = kw.argument.parts.find(p => typeof p === 'string');
|
|
39
|
+
if (text) {
|
|
40
|
+
targetName = text.trim();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else if (kw.argument.type === 'Identifier') {
|
|
44
|
+
targetName = kw.argument.name;
|
|
45
|
+
}
|
|
46
|
+
if (targetName) {
|
|
47
|
+
// Skip URLs (external gotos)
|
|
48
|
+
if (!targetName.startsWith('http://') && !targetName.startsWith('https://')) {
|
|
49
|
+
gotoStatements.push({
|
|
50
|
+
target: targetName,
|
|
51
|
+
line: kw.loc.start.line,
|
|
52
|
+
column: kw.loc.start.column,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Recurse into body
|
|
58
|
+
for (const stmt of kw.body) {
|
|
59
|
+
collectLabels(stmt);
|
|
60
|
+
}
|
|
61
|
+
// Recurse into sub-keywords
|
|
62
|
+
for (const sub of kw.subKeywords) {
|
|
63
|
+
for (const stmt of sub.body) {
|
|
64
|
+
collectLabels(stmt);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (node.type === 'AnswerOption') {
|
|
69
|
+
for (const stmt of node.body) {
|
|
70
|
+
collectLabels(stmt);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
Program(node) {
|
|
76
|
+
// Collect all label definitions and goto usages
|
|
77
|
+
collectLabels(node);
|
|
78
|
+
// Report gotos that target undefined labels
|
|
79
|
+
for (const goto of gotoStatements) {
|
|
80
|
+
if (!definedLabels.has(goto.target)) {
|
|
81
|
+
context.report({
|
|
82
|
+
message: `*goto target '${goto.target}' is not defined`,
|
|
83
|
+
line: goto.line,
|
|
84
|
+
column: goto.column,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=no-invalid-goto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-invalid-goto.js","sourceRoot":"","sources":["../../../src/linter/rules/no-invalid-goto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-single-quotes.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-single-quotes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAG1D,eAAO,MAAM,cAAc,EAAE,QAkD5B,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export const noSingleQuotes = {
|
|
2
|
+
name: 'no-single-quotes',
|
|
3
|
+
description: 'Disallow single quotes for strings (use double quotes)',
|
|
4
|
+
severity: 'error',
|
|
5
|
+
create(context) {
|
|
6
|
+
return {
|
|
7
|
+
Program(_node) {
|
|
8
|
+
const source = context.getSourceCode();
|
|
9
|
+
const lines = source.split(/\r?\n/);
|
|
10
|
+
lines.forEach((line, lineIndex) => {
|
|
11
|
+
const lineNumber = lineIndex + 1;
|
|
12
|
+
const trimmedLine = line.trimStart();
|
|
13
|
+
// Skip blank lines
|
|
14
|
+
if (trimmedLine.length === 0)
|
|
15
|
+
return;
|
|
16
|
+
// Skip comments (allowed to have single quotes)
|
|
17
|
+
if (trimmedLine.startsWith('--'))
|
|
18
|
+
return;
|
|
19
|
+
// Check for expression lines (>> ...)
|
|
20
|
+
if (trimmedLine.startsWith('>>')) {
|
|
21
|
+
checkExpressionForSingleQuotes(line, lineNumber, context);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Check for conditional keywords (*if:, *while:, etc.) with expressions
|
|
25
|
+
const conditionalMatch = trimmedLine.match(/^\*(?:if|while|for):\s*(.+)$/);
|
|
26
|
+
if (conditionalMatch) {
|
|
27
|
+
const expression = conditionalMatch[1];
|
|
28
|
+
const exprStartCol = line.indexOf(expression) + 1;
|
|
29
|
+
checkStringForSingleQuotes(expression, lineNumber, exprStartCol, context);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Check for *path: lines (they may contain expressions with strings)
|
|
33
|
+
const pathMatch = trimmedLine.match(/^\*path:\s*(.+)$/);
|
|
34
|
+
if (pathMatch) {
|
|
35
|
+
const pathValue = pathMatch[1];
|
|
36
|
+
const pathStartCol = line.indexOf(pathValue) + 1;
|
|
37
|
+
checkStringForSingleQuotes(pathValue, lineNumber, pathStartCol, context);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// All other lines (visible text, keyword arguments, answer options) are allowed to have single quotes
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
function checkExpressionForSingleQuotes(line, lineNumber, context) {
|
|
47
|
+
const exprMatch = line.match(/^(\t*)>>\s*(.+)$/);
|
|
48
|
+
if (!exprMatch)
|
|
49
|
+
return;
|
|
50
|
+
const expression = exprMatch[2];
|
|
51
|
+
const exprStartCol = line.indexOf(expression) + 1;
|
|
52
|
+
checkStringForSingleQuotes(expression, lineNumber, exprStartCol, context);
|
|
53
|
+
}
|
|
54
|
+
function checkStringForSingleQuotes(text, lineNumber, startCol, context) {
|
|
55
|
+
let inDoubleQuotes = false;
|
|
56
|
+
for (let i = 0; i < text.length; i++) {
|
|
57
|
+
const ch = text[i];
|
|
58
|
+
// Toggle double quote state
|
|
59
|
+
if (ch === '"') {
|
|
60
|
+
inDoubleQuotes = !inDoubleQuotes;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// If we find a single quote outside of double quotes, that's an error
|
|
64
|
+
if (ch === "'" && !inDoubleQuotes) {
|
|
65
|
+
context.report({
|
|
66
|
+
message: "Single quotes are not valid for strings in GuidedTrack. Use double quotes instead.",
|
|
67
|
+
line: lineNumber,
|
|
68
|
+
column: startCol + i,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=no-single-quotes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-single-quotes.js","sourceRoot":"","sources":["../../../src/linter/rules/no-single-quotes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-unclosed-bracket.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-unclosed-bracket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAS1D,eAAO,MAAM,iBAAiB,EAAE,QAoH/B,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export const noUnclosedBracket = {
|
|
2
|
+
name: 'no-unclosed-bracket',
|
|
3
|
+
description: 'Detect unclosed brackets/braces',
|
|
4
|
+
severity: 'error',
|
|
5
|
+
create(context) {
|
|
6
|
+
return {
|
|
7
|
+
Program(_node) {
|
|
8
|
+
const source = context.getSourceCode();
|
|
9
|
+
const lines = source.split('\n');
|
|
10
|
+
const stack = [];
|
|
11
|
+
const pairs = {
|
|
12
|
+
'(': ')',
|
|
13
|
+
'[': ']',
|
|
14
|
+
'{': '}',
|
|
15
|
+
};
|
|
16
|
+
const closers = {
|
|
17
|
+
')': '(',
|
|
18
|
+
']': '[',
|
|
19
|
+
'}': '{',
|
|
20
|
+
};
|
|
21
|
+
// Expression keywords that are followed by expressions
|
|
22
|
+
const exprKeywords = ['if', 'while', 'for', 'repeat', 'goto', 'return'];
|
|
23
|
+
for (let i = 0; i < lines.length; i++) {
|
|
24
|
+
const line = lines[i];
|
|
25
|
+
const lineNumber = i + 1;
|
|
26
|
+
const trimmedLine = line.trim();
|
|
27
|
+
// Only check brackets in expression contexts:
|
|
28
|
+
// 1. Lines starting with >>
|
|
29
|
+
// 2. Lines starting with expression keywords (*if:, *while:, etc.)
|
|
30
|
+
let isExpressionContext = false;
|
|
31
|
+
if (trimmedLine.startsWith('>>')) {
|
|
32
|
+
isExpressionContext = true;
|
|
33
|
+
}
|
|
34
|
+
else if (trimmedLine.startsWith('*')) {
|
|
35
|
+
// Check if it's an expression keyword
|
|
36
|
+
for (const keyword of exprKeywords) {
|
|
37
|
+
if (trimmedLine.toLowerCase().startsWith(`*${keyword}:`)) {
|
|
38
|
+
isExpressionContext = true;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Skip checking if not in an expression context
|
|
44
|
+
if (!isExpressionContext)
|
|
45
|
+
continue;
|
|
46
|
+
let inString = false;
|
|
47
|
+
let stringChar = '';
|
|
48
|
+
for (let j = 0; j < line.length; j++) {
|
|
49
|
+
const ch = line[j];
|
|
50
|
+
// Skip if in comment
|
|
51
|
+
if (!inString && ch === '-' && line[j + 1] === '-') {
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
// Handle strings
|
|
55
|
+
if (!inString && (ch === '"' || ch === "'")) {
|
|
56
|
+
inString = true;
|
|
57
|
+
stringChar = ch;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (inString && ch === stringChar) {
|
|
61
|
+
inString = false;
|
|
62
|
+
stringChar = '';
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Skip bracket checking inside strings
|
|
66
|
+
if (inString)
|
|
67
|
+
continue;
|
|
68
|
+
// Opening brackets
|
|
69
|
+
if (pairs[ch]) {
|
|
70
|
+
stack.push({ char: ch, line: lineNumber, column: j + 1 });
|
|
71
|
+
}
|
|
72
|
+
// Closing brackets
|
|
73
|
+
if (closers[ch]) {
|
|
74
|
+
if (stack.length === 0) {
|
|
75
|
+
context.report({
|
|
76
|
+
message: `Unexpected closing bracket '${ch}'`,
|
|
77
|
+
line: lineNumber,
|
|
78
|
+
column: j + 1,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const top = stack.pop();
|
|
83
|
+
if (pairs[top.char] !== ch) {
|
|
84
|
+
context.report({
|
|
85
|
+
message: `Mismatched brackets: expected '${pairs[top.char]}' but found '${ch}'`,
|
|
86
|
+
line: lineNumber,
|
|
87
|
+
column: j + 1,
|
|
88
|
+
});
|
|
89
|
+
// Put back the opener since it's not matched
|
|
90
|
+
stack.push(top);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Report any unclosed brackets
|
|
97
|
+
for (const bracket of stack) {
|
|
98
|
+
context.report({
|
|
99
|
+
message: `Unclosed bracket '${bracket.char}' (missing '${pairs[bracket.char]}')`,
|
|
100
|
+
line: bracket.line,
|
|
101
|
+
column: bracket.column,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=no-unclosed-bracket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-unclosed-bracket.js","sourceRoot":"","sources":["../../../src/linter/rules/no-unclosed-bracket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-unclosed-string.d.ts","sourceRoot":"","sources":["../../../src/linter/rules/no-unclosed-string.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,cAAc,CAAC;AAG1D,eAAO,MAAM,gBAAgB,EAAE,QAoD9B,CAAC"}
|