kopytko-linter 0.1.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.
Files changed (102) hide show
  1. package/README.md +190 -0
  2. package/dist/bin/kopytko-lint.d.ts +3 -0
  3. package/dist/bin/kopytko-lint.d.ts.map +1 -0
  4. package/dist/bin/kopytko-lint.js +118 -0
  5. package/dist/bin/kopytko-lint.js.map +1 -0
  6. package/dist/src/analysis/fsWrapper.d.ts +19 -0
  7. package/dist/src/analysis/fsWrapper.d.ts.map +1 -0
  8. package/dist/src/analysis/fsWrapper.js +62 -0
  9. package/dist/src/analysis/fsWrapper.js.map +1 -0
  10. package/dist/src/analysis/functionIndex.d.ts +19 -0
  11. package/dist/src/analysis/functionIndex.d.ts.map +1 -0
  12. package/dist/src/analysis/functionIndex.js +69 -0
  13. package/dist/src/analysis/functionIndex.js.map +1 -0
  14. package/dist/src/analysis/globMatcher.d.ts +8 -0
  15. package/dist/src/analysis/globMatcher.d.ts.map +1 -0
  16. package/dist/src/analysis/globMatcher.js +27 -0
  17. package/dist/src/analysis/globMatcher.js.map +1 -0
  18. package/dist/src/analysis/importParser.d.ts +22 -0
  19. package/dist/src/analysis/importParser.d.ts.map +1 -0
  20. package/dist/src/analysis/importParser.js +131 -0
  21. package/dist/src/analysis/importParser.js.map +1 -0
  22. package/dist/src/analysis/patternSiblings.d.ts +13 -0
  23. package/dist/src/analysis/patternSiblings.d.ts.map +1 -0
  24. package/dist/src/analysis/patternSiblings.js +91 -0
  25. package/dist/src/analysis/patternSiblings.js.map +1 -0
  26. package/dist/src/analysis/scopeAnalysis.d.ts +17 -0
  27. package/dist/src/analysis/scopeAnalysis.d.ts.map +1 -0
  28. package/dist/src/analysis/scopeAnalysis.js +180 -0
  29. package/dist/src/analysis/scopeAnalysis.js.map +1 -0
  30. package/dist/src/analysis/testUtils.d.ts +17 -0
  31. package/dist/src/analysis/testUtils.d.ts.map +1 -0
  32. package/dist/src/analysis/testUtils.js +124 -0
  33. package/dist/src/analysis/testUtils.js.map +1 -0
  34. package/dist/src/analysis/textUtils.d.ts +9 -0
  35. package/dist/src/analysis/textUtils.d.ts.map +1 -0
  36. package/dist/src/analysis/textUtils.js +45 -0
  37. package/dist/src/analysis/textUtils.js.map +1 -0
  38. package/dist/src/catalog/builtins.d.ts +26 -0
  39. package/dist/src/catalog/builtins.d.ts.map +1 -0
  40. package/dist/src/catalog/builtins.js +123 -0
  41. package/dist/src/catalog/builtins.js.map +1 -0
  42. package/dist/src/catalog/components.d.ts +8 -0
  43. package/dist/src/catalog/components.d.ts.map +1 -0
  44. package/dist/src/catalog/components.js +35 -0
  45. package/dist/src/catalog/components.js.map +1 -0
  46. package/dist/src/config.d.ts +23 -0
  47. package/dist/src/config.d.ts.map +1 -0
  48. package/dist/src/config.js +167 -0
  49. package/dist/src/config.js.map +1 -0
  50. package/dist/src/context.d.ts +22 -0
  51. package/dist/src/context.d.ts.map +1 -0
  52. package/dist/src/context.js +3 -0
  53. package/dist/src/context.js.map +1 -0
  54. package/dist/src/index.d.ts +28 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +54 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/jsonc.d.ts +6 -0
  59. package/dist/src/jsonc.d.ts.map +1 -0
  60. package/dist/src/jsonc.js +46 -0
  61. package/dist/src/jsonc.js.map +1 -0
  62. package/dist/src/linter.d.ts +19 -0
  63. package/dist/src/linter.d.ts.map +1 -0
  64. package/dist/src/linter.js +274 -0
  65. package/dist/src/linter.js.map +1 -0
  66. package/dist/src/output/jsonFormatter.d.ts +3 -0
  67. package/dist/src/output/jsonFormatter.d.ts.map +1 -0
  68. package/dist/src/output/jsonFormatter.js +26 -0
  69. package/dist/src/output/jsonFormatter.js.map +1 -0
  70. package/dist/src/output/sarifFormatter.d.ts +3 -0
  71. package/dist/src/output/sarifFormatter.d.ts.map +1 -0
  72. package/dist/src/output/sarifFormatter.js +110 -0
  73. package/dist/src/output/sarifFormatter.js.map +1 -0
  74. package/dist/src/output/textFormatter.d.ts +3 -0
  75. package/dist/src/output/textFormatter.d.ts.map +1 -0
  76. package/dist/src/output/textFormatter.js +61 -0
  77. package/dist/src/output/textFormatter.js.map +1 -0
  78. package/dist/src/rules/identifierRules.d.ts +6 -0
  79. package/dist/src/rules/identifierRules.d.ts.map +1 -0
  80. package/dist/src/rules/identifierRules.js +322 -0
  81. package/dist/src/rules/identifierRules.js.map +1 -0
  82. package/dist/src/rules/importRules.d.ts +6 -0
  83. package/dist/src/rules/importRules.d.ts.map +1 -0
  84. package/dist/src/rules/importRules.js +164 -0
  85. package/dist/src/rules/importRules.js.map +1 -0
  86. package/dist/src/rules/index.d.ts +4 -0
  87. package/dist/src/rules/index.d.ts.map +1 -0
  88. package/dist/src/rules/index.js +21 -0
  89. package/dist/src/rules/index.js.map +1 -0
  90. package/dist/src/rules/syntaxRules.d.ts +6 -0
  91. package/dist/src/rules/syntaxRules.d.ts.map +1 -0
  92. package/dist/src/rules/syntaxRules.js +221 -0
  93. package/dist/src/rules/syntaxRules.js.map +1 -0
  94. package/dist/src/rules/testRules.d.ts +3 -0
  95. package/dist/src/rules/testRules.d.ts.map +1 -0
  96. package/dist/src/rules/testRules.js +79 -0
  97. package/dist/src/rules/testRules.js.map +1 -0
  98. package/dist/src/types.d.ts +54 -0
  99. package/dist/src/types.d.ts.map +1 -0
  100. package/dist/src/types.js +3 -0
  101. package/dist/src/types.js.map +1 -0
  102. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # kopytko-linter
2
+
3
+ BrightScript linter for the [Kopytko ecosystem](https://github.com/bchelkowski/vscode-kopytko). Use as a CLI tool in CI pipelines or import as a library.
4
+
5
+ ## Features
6
+
7
+ - **19 diagnostic rules** covering imports, identifiers, syntax, and test structure
8
+ - **Configurable severity** per rule (`error`, `warning`, `info`, `hint`, `off`)
9
+ - **Three output formats**: text (terminal), JSON, [SARIF](https://sarifweb.azurewebsites.net/) (GitHub Code Scanning)
10
+ - **Config file support**: `kopytko-linter.json` or `.vscode/settings.json`
11
+ - **Library API** for integration with editors and build tools
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install --save-dev kopytko-linter
17
+ ```
18
+
19
+ ## CLI Usage
20
+
21
+ ```bash
22
+ # Lint the current project
23
+ npx kopytko-lint
24
+
25
+ # CI mode — exit with code 1 if any errors are found
26
+ npx kopytko-lint --check
27
+
28
+ # Output as JSON
29
+ npx kopytko-lint --format json
30
+
31
+ # Output SARIF for GitHub Code Scanning
32
+ npx kopytko-lint --format sarif > results.sarif
33
+
34
+ # Use a specific config file
35
+ npx kopytko-lint --config my-rules.json
36
+
37
+ # Override source directory
38
+ npx kopytko-lint --source-dir components
39
+ ```
40
+
41
+ ### CLI Options
42
+
43
+ | Option | Description |
44
+ |---|---|
45
+ | `--check` | Exit with code 1 if any errors are found (for CI) |
46
+ | `--format`, `-f` | Output format: `text` (default), `json`, `sarif` |
47
+ | `--config`, `-c` | Path to config file |
48
+ | `--source-dir` | Override source directory (default: from config or `src`) |
49
+ | `--no-color` | Disable colored terminal output |
50
+ | `--help`, `-h` | Show help |
51
+ | `--version`, `-v` | Show version |
52
+
53
+ ## Configuration
54
+
55
+ ### Config File Resolution
56
+
57
+ Configuration is resolved in this order:
58
+
59
+ 1. `--config <file>` CLI flag
60
+ 2. `kopytko-linter.json` in project root
61
+ 3. `.vscode/settings.json` (`kopytko.lint.*` keys)
62
+ 4. Default config (all rules enabled at default severity)
63
+
64
+ ### Example `kopytko-linter.json`
65
+
66
+ ```json
67
+ {
68
+ "rules": {
69
+ "import/unused": "off",
70
+ "identifier/shadows-builtin": "warning",
71
+ "syntax/trailing-comma": "error"
72
+ },
73
+ "sourceDir": "src",
74
+ "resolveModules": true,
75
+ "generatedPaths": ["/source/generated/**"],
76
+ "generatedModules": [],
77
+ "siblingPatterns": []
78
+ }
79
+ ```
80
+
81
+ ### VS Code Settings
82
+
83
+ Add `kopytko.lint.*` keys to `.vscode/settings.json`:
84
+
85
+ ```json
86
+ {
87
+ "kopytko.lint.sourceDir": "src",
88
+ "kopytko.lint.rules.import/unused": "off",
89
+ "kopytko.lint.rules.identifier/shadows-builtin": "warning"
90
+ }
91
+ ```
92
+
93
+ ## Rules
94
+
95
+ ### Import Rules
96
+
97
+ | Rule | Default | Description |
98
+ |---|---|---|
99
+ | `import/duplicate` | error | Same import path imported twice |
100
+ | `import/missing-path` | error | `@import` / `@mock` with empty path |
101
+ | `import/path-not-absolute` | warning | Import path doesn't start with `/` |
102
+ | `import/wrong-comment-style` | error | `@import` written with `"` instead of `'` comment |
103
+ | `import/build-generated` | info | Unresolved path matches a configured generated-path pattern |
104
+ | `import/unresolved` | warning | Cannot resolve import to a file on disk |
105
+ | `import/unused` | warning | Imported file's functions are never referenced |
106
+
107
+ ### Identifier Rules
108
+
109
+ | Rule | Default | Description |
110
+ |---|---|---|
111
+ | `identifier/undefined-function` | error | Function call to unknown name |
112
+ | `identifier/wrong-arg-count` | error | Built-in function called with wrong number of arguments |
113
+ | `identifier/undefined-variable` | error | Variable used but never assigned in the enclosing scope |
114
+ | `identifier/shadows-builtin` | error | Variable name shadows a BrightScript built-in function |
115
+ | `identifier/unused-parameter` | hint | Function parameter never used in body (prefix `_` to suppress) |
116
+
117
+ ### Syntax Rules
118
+
119
+ | Rule | Default | Description |
120
+ |---|---|---|
121
+ | `throw/invalid-value` | warning | `throw` with numeric, array, or `invalid` value |
122
+ | `throw/missing-message` | warning | Thrown associative array missing `message` field |
123
+ | `createobject/unknown-component` | warning | `CreateObject("...")` with unrecognized component name |
124
+ | `syntax/trailing-comma` | error | Trailing comma after `return` value |
125
+ | `syntax/flow-outside-loop` | error | `continue for`/`exit while` outside matching loop |
126
+
127
+ ### Test Rules
128
+
129
+ | Rule | Default | Description |
130
+ |---|---|---|
131
+ | `test/missing-mock-annotation` | warning | `mockFunction("X")` targets a function not in any `@mock`'ed file |
132
+ | `test/missing-return-ts` | warning | `TestSuite__*` function missing `return ts` |
133
+
134
+ ## Library API
135
+
136
+ ```typescript
137
+ import { lintProject, lintFile, DEFAULT_LINTER_CONFIG } from 'kopytko-linter';
138
+ import type { LintContext, LintResult, LintDiagnostic } from 'kopytko-linter';
139
+
140
+ // Lint a whole project (standalone mode)
141
+ const result: LintResult = lintProject('/path/to/project');
142
+ console.log(`${result.errorCount} errors, ${result.warningCount} warnings`);
143
+
144
+ // Lint a single file (library mode — provide your own context)
145
+ const context: LintContext = {
146
+ knownFuncNames: new Set(['init', 'myhelper']),
147
+ parseImports: (text) => parseImports(text),
148
+ resolveImportPath: (path) => /* resolve path */,
149
+ importExists: (path) => /* check existence */,
150
+ readFile: (path) => /* read file */,
151
+ parseFunctionsFromFile: (path) => /* parse functions */,
152
+ getSiblingFiles: (path) => /* find siblings */,
153
+ isTestFile: (path) => path.endsWith('.test.brs'),
154
+ generatedPaths: [],
155
+ generatedModules: [],
156
+ siblingPatterns: [],
157
+ };
158
+
159
+ const diagnostics: LintDiagnostic[] = lintFile(
160
+ '/path/to/file.brs',
161
+ fileContent,
162
+ context,
163
+ DEFAULT_LINTER_CONFIG,
164
+ );
165
+ ```
166
+
167
+ ## CI Integration
168
+
169
+ ### GitHub Actions
170
+
171
+ ```yaml
172
+ - name: Lint BrightScript
173
+ run: npx kopytko-lint --check
174
+ ```
175
+
176
+ ### GitHub Code Scanning (SARIF)
177
+
178
+ ```yaml
179
+ - name: Lint BrightScript
180
+ run: npx kopytko-lint --format sarif > results.sarif
181
+
182
+ - name: Upload SARIF
183
+ uses: github/codeql-action/upload-sarif@v3
184
+ with:
185
+ sarif_file: results.sarif
186
+ ```
187
+
188
+ ## License
189
+
190
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=kopytko-lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kopytko-lint.d.ts","sourceRoot":"","sources":["../../bin/kopytko-lint.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const linter_1 = require("../src/linter");
5
+ const config_1 = require("../src/config");
6
+ const textFormatter_1 = require("../src/output/textFormatter");
7
+ const jsonFormatter_1 = require("../src/output/jsonFormatter");
8
+ const sarifFormatter_1 = require("../src/output/sarifFormatter");
9
+ function parseArgs(argv) {
10
+ const options = {
11
+ format: 'text',
12
+ check: false,
13
+ noColor: false,
14
+ };
15
+ for (let i = 2; i < argv.length; i++) {
16
+ const arg = argv[i];
17
+ if (arg === '--format' || arg === '-f') {
18
+ const value = argv[++i];
19
+ if (value === 'text' || value === 'json' || value === 'sarif') {
20
+ options.format = value;
21
+ }
22
+ else {
23
+ console.error(`Unknown format: ${value}. Use text, json, or sarif.`);
24
+ process.exit(2);
25
+ }
26
+ }
27
+ else if (arg === '--config' || arg === '-c') {
28
+ options.configPath = argv[++i];
29
+ }
30
+ else if (arg === '--source-dir') {
31
+ options.sourceDir = argv[++i];
32
+ }
33
+ else if (arg === '--check') {
34
+ options.check = true;
35
+ }
36
+ else if (arg === '--no-color') {
37
+ options.noColor = true;
38
+ }
39
+ else if (arg === '--help' || arg === '-h') {
40
+ printHelp();
41
+ process.exit(0);
42
+ }
43
+ else if (arg === '--version' || arg === '-v') {
44
+ printVersion();
45
+ process.exit(0);
46
+ }
47
+ else if (arg.startsWith('-')) {
48
+ console.error(`Unknown option: ${arg}. Use --help for usage.`);
49
+ process.exit(2);
50
+ }
51
+ }
52
+ return options;
53
+ }
54
+ function printHelp() {
55
+ console.log(`
56
+ kopytko-lint — BrightScript linter for the Kopytko ecosystem
57
+
58
+ Usage:
59
+ kopytko-lint [options]
60
+
61
+ Options:
62
+ --check Exit with code 1 if any errors are found (for CI)
63
+ --format, -f Output format: text (default), json, sarif
64
+ --config, -c Path to config file (default: kopytko-linter.json)
65
+ --source-dir Source directory (default: from config or "src")
66
+ --no-color Disable colored output
67
+ --help, -h Show this help message
68
+ --version, -v Show version
69
+
70
+ Config resolution (priority order):
71
+ 1. --config <file>
72
+ 2. kopytko-linter.json in project root
73
+ 3. .vscode/settings.json (kopytko.lint.* keys)
74
+ 4. Default config (all rules enabled)
75
+
76
+ Examples:
77
+ kopytko-lint # lint current project with default config
78
+ kopytko-lint --check # CI mode — exit 1 on errors
79
+ kopytko-lint --format sarif # output SARIF for GitHub Code Scanning
80
+ kopytko-lint --config my-rules.json
81
+ `);
82
+ }
83
+ function printVersion() {
84
+ try {
85
+ const pkg = require('../../package.json');
86
+ console.log(`kopytko-lint v${pkg.version}`);
87
+ }
88
+ catch {
89
+ console.log('kopytko-lint (development)');
90
+ }
91
+ }
92
+ function main() {
93
+ const options = parseArgs(process.argv);
94
+ const projectRoot = process.cwd();
95
+ const config = (0, config_1.resolveConfig)(projectRoot, options.configPath);
96
+ if (options.sourceDir) {
97
+ config.sourceDir = options.sourceDir;
98
+ }
99
+ const result = (0, linter_1.lintProject)(projectRoot, config);
100
+ // Output
101
+ switch (options.format) {
102
+ case 'json':
103
+ console.log((0, jsonFormatter_1.formatJson)(result));
104
+ break;
105
+ case 'sarif':
106
+ console.log((0, sarifFormatter_1.formatSarif)(result, projectRoot));
107
+ break;
108
+ default:
109
+ console.log((0, textFormatter_1.formatText)(result, !options.noColor));
110
+ break;
111
+ }
112
+ // Exit code
113
+ if (options.check && result.errorCount > 0) {
114
+ process.exit(1);
115
+ }
116
+ }
117
+ main();
118
+ //# sourceMappingURL=kopytko-lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kopytko-lint.js","sourceRoot":"","sources":["../../bin/kopytko-lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ interface DirEntry {
2
+ name: string;
3
+ isDirectory: boolean;
4
+ }
5
+ /**
6
+ * Thin fs wrapper. All filesystem access goes through this module so that
7
+ * tests can stub individual functions via `sinon.stub(fsWrapper, 'existsSync')`.
8
+ *
9
+ * Exported as a mutable object (not direct function exports) to ensure
10
+ * property descriptors remain configurable under all module systems.
11
+ */
12
+ declare const fsWrapper: {
13
+ existsSync(filePath: string): boolean;
14
+ readFileSync(filePath: string, encoding: BufferEncoding): string;
15
+ readdirSync(dirPath: string): string[];
16
+ readdirTyped(dirPath: string): DirEntry[];
17
+ };
18
+ export default fsWrapper;
19
+ //# sourceMappingURL=fsWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsWrapper.d.ts","sourceRoot":"","sources":["../../../src/analysis/fsWrapper.ts"],"names":[],"mappings":"AAEA,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,SAAS;yBACQ,MAAM,GAAG,OAAO;2BAId,MAAM,YAAY,cAAc,GAAG,MAAM;yBAI3C,MAAM,GAAG,MAAM,EAAE;0BAIhB,MAAM,GAAG,QAAQ,EAAE;CAM1C,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("fs"));
37
+ /**
38
+ * Thin fs wrapper. All filesystem access goes through this module so that
39
+ * tests can stub individual functions via `sinon.stub(fsWrapper, 'existsSync')`.
40
+ *
41
+ * Exported as a mutable object (not direct function exports) to ensure
42
+ * property descriptors remain configurable under all module systems.
43
+ */
44
+ const fsWrapper = {
45
+ existsSync(filePath) {
46
+ return fs.existsSync(filePath);
47
+ },
48
+ readFileSync(filePath, encoding) {
49
+ return fs.readFileSync(filePath, encoding);
50
+ },
51
+ readdirSync(dirPath) {
52
+ return fs.readdirSync(dirPath);
53
+ },
54
+ readdirTyped(dirPath) {
55
+ return fs.readdirSync(dirPath, { withFileTypes: true }).map((entry) => ({
56
+ name: entry.name,
57
+ isDirectory: entry.isDirectory(),
58
+ }));
59
+ },
60
+ };
61
+ exports.default = fsWrapper;
62
+ //# sourceMappingURL=fsWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsWrapper.js","sourceRoot":"","sources":["../../../src/analysis/fsWrapper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAOzB;;;;;;GAMG;AACH,MAAM,SAAS,GAAG;IAChB,UAAU,CAAC,QAAgB;QACzB,OAAO,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAED,YAAY,CAAC,QAAgB,EAAE,QAAwB;QACrD,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAW,CAAC;IACvD,CAAC;IAED,WAAW,CAAC,OAAe;QACzB,OAAO,EAAE,CAAC,WAAW,CAAC,OAAO,CAAa,CAAC;IAC7C,CAAC;IAED,YAAY,CAAC,OAAe;QAC1B,OAAO,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACtE,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE;SACjC,CAAC,CAAC,CAAC;IACN,CAAC;CACF,CAAC;AAEF,kBAAe,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { FunctionDefinition } from '../types';
2
+ export interface InnerMethodDefinition {
3
+ name: string;
4
+ nameLower: string;
5
+ line: number;
6
+ column: number;
7
+ filePath: string;
8
+ ownerFunction?: string;
9
+ }
10
+ /**
11
+ * Parses all top-level function/sub definitions from a BrightScript text.
12
+ */
13
+ export declare function parseFunctionDefs(text: string, filePath: string, preLines?: string[]): FunctionDefinition[];
14
+ /**
15
+ * Parses all associative-array method assignments of the form
16
+ * `<obj>.<name> = function|sub (...)` from a BrightScript text.
17
+ */
18
+ export declare function parseInnerMethodDefs(text: string, filePath: string): InnerMethodDefinition[];
19
+ //# sourceMappingURL=functionIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functionIndex.d.ts","sourceRoot":"","sources":["../../../src/analysis/functionIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAOnD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAkB3G;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CA+B5F"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFunctionDefs = parseFunctionDefs;
4
+ exports.parseInnerMethodDefs = parseInnerMethodDefs;
5
+ const FUNC_PREFIX_RE = /^\s*(?:function|sub)\s+/i;
6
+ const FUNC_FULL_RE = /^\s*(?:function|sub)\s+(\w+)\s*\(/i;
7
+ const INNER_METHOD_RE = /^\s*\w+\.(\w+)\s*=\s*(?:function|sub)\s*\(/i;
8
+ const INNER_COLON_METHOD_RE = /^\s*(\w+)\s*:\s*(?:function|sub)\s*\(/i;
9
+ /**
10
+ * Parses all top-level function/sub definitions from a BrightScript text.
11
+ */
12
+ function parseFunctionDefs(text, filePath, preLines) {
13
+ const lines = preLines ?? text.split(/\r?\n/);
14
+ const defs = [];
15
+ for (let i = 0; i < lines.length; i++) {
16
+ const match = FUNC_FULL_RE.exec(lines[i]);
17
+ if (!match)
18
+ continue;
19
+ const prefixMatch = FUNC_PREFIX_RE.exec(lines[i]);
20
+ const column = prefixMatch ? prefixMatch[0].length : 0;
21
+ defs.push({
22
+ name: match[1],
23
+ nameLower: match[1].toLowerCase(),
24
+ line: i,
25
+ column,
26
+ filePath,
27
+ signature: lines[i].trim(),
28
+ });
29
+ }
30
+ return defs;
31
+ }
32
+ /**
33
+ * Parses all associative-array method assignments of the form
34
+ * `<obj>.<name> = function|sub (...)` from a BrightScript text.
35
+ */
36
+ function parseInnerMethodDefs(text, filePath) {
37
+ const lines = text.split(/\r?\n/);
38
+ const funcDefs = parseFunctionDefs(text, filePath, lines);
39
+ const defs = [];
40
+ for (let i = 0; i < lines.length; i++) {
41
+ const line = lines[i];
42
+ if (/^\s*'/.test(line))
43
+ continue;
44
+ let name, column;
45
+ const dotMatch = INNER_METHOD_RE.exec(line);
46
+ if (dotMatch) {
47
+ name = dotMatch[1];
48
+ const dotIdx = line.indexOf('.');
49
+ column = line.indexOf(name, dotIdx >= 0 ? dotIdx : 0);
50
+ }
51
+ else {
52
+ const colonMatch = INNER_COLON_METHOD_RE.exec(line);
53
+ if (!colonMatch)
54
+ continue;
55
+ name = colonMatch[1];
56
+ column = line.search(/\S/);
57
+ }
58
+ let ownerFunction;
59
+ for (let j = funcDefs.length - 1; j >= 0; j--) {
60
+ if (funcDefs[j].line <= i) {
61
+ ownerFunction = funcDefs[j].name;
62
+ break;
63
+ }
64
+ }
65
+ defs.push({ name, nameLower: name.toLowerCase(), line: i, column, filePath, ownerFunction });
66
+ }
67
+ return defs;
68
+ }
69
+ //# sourceMappingURL=functionIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functionIndex.js","sourceRoot":"","sources":["../../../src/analysis/functionIndex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Minimal glob matcher supporting `*` (any chars except `/`) and `**` (any chars including `/`).
3
+ * Used to match @import paths against user-configured generated-file patterns.
4
+ */
5
+ export declare function matchesGlob(str: string, pattern: string): boolean;
6
+ /** Returns the first pattern that matches, or undefined if none match. */
7
+ export declare function findMatchingGlob(str: string, patterns: string[]): string | undefined;
8
+ //# sourceMappingURL=globMatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globMatcher.d.ts","sourceRoot":"","sources":["../../../src/analysis/globMatcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAYjE;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAEpF"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal glob matcher supporting `*` (any chars except `/`) and `**` (any chars including `/`).
4
+ * Used to match @import paths against user-configured generated-file patterns.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.matchesGlob = matchesGlob;
8
+ exports.findMatchingGlob = findMatchingGlob;
9
+ const _globRegexCache = new Map();
10
+ function matchesGlob(str, pattern) {
11
+ let regex = _globRegexCache.get(pattern);
12
+ if (!regex) {
13
+ const regexSource = pattern
14
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // escape regex metacharacters
15
+ .replace(/\*\*/g, '\x00') // placeholder for **
16
+ .replace(/\*/g, '[^/]*') // * → any non-slash chars
17
+ .replace(/\x00/g, '.*'); // ** → any chars (including /)
18
+ regex = new RegExp('^' + regexSource + '$');
19
+ _globRegexCache.set(pattern, regex);
20
+ }
21
+ return regex.test(str);
22
+ }
23
+ /** Returns the first pattern that matches, or undefined if none match. */
24
+ function findMatchingGlob(str, patterns) {
25
+ return patterns.find((p) => matchesGlob(str, p));
26
+ }
27
+ //# sourceMappingURL=globMatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globMatcher.js","sourceRoot":"","sources":["../../../src/analysis/globMatcher.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAIH,kCAYC;AAGD,4CAEC;AAnBD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;AAElD,SAAgB,WAAW,CAAC,GAAW,EAAE,OAAe;IACtD,IAAI,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,WAAW,GAAG,OAAO;aACxB,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,8BAA8B;aACnE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAc,qBAAqB;aAC3D,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAe,0BAA0B;aAChE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAe,+BAA+B;QACxE,KAAK,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,WAAW,GAAG,GAAG,CAAC,CAAC;QAC5C,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,0EAA0E;AAC1E,SAAgB,gBAAgB,CAAC,GAAW,EAAE,QAAkB;IAC9D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { KopytkoImport } from '../types';
2
+ export declare function parseImports(text: string): KopytkoImport[];
3
+ export interface ImportResolverOptions {
4
+ workspaceFolders: string[];
5
+ sourceDir: string;
6
+ resolveModules: boolean;
7
+ }
8
+ export declare class ImportResolver {
9
+ private readonly options;
10
+ private packageCache;
11
+ constructor(options: ImportResolverOptions);
12
+ getWorkspaceFolders(): string[];
13
+ getSourceDir(): string;
14
+ parseImports(text: string): KopytkoImport[];
15
+ resolveImportPath(imp: KopytkoImport, documentPath: string): string | undefined;
16
+ importExists(imp: KopytkoImport, documentPath: string): boolean;
17
+ invalidatePackageCache(): void;
18
+ private resolveInternalImport;
19
+ private resolveExternalImport;
20
+ resolvePackageBaseDir(packageName: string): string | undefined;
21
+ }
22
+ //# sourceMappingURL=importParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importParser.d.ts","sourceRoot":"","sources":["../../../src/analysis/importParser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAK9C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAkB1D;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,YAAY,CAAoC;gBAE5C,OAAO,EAAE,qBAAqB;IAI1C,mBAAmB,IAAI,MAAM,EAAE;IAI/B,YAAY,IAAI,MAAM;IAItB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE;IAI3C,iBAAiB,CAAC,GAAG,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAO/E,YAAY,CAAC,GAAG,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAI/D,sBAAsB,IAAI,IAAI;IAI9B,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,qBAAqB;IAY7B,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAa/D"}