norn-cli 2.3.0 → 2.4.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 (92) hide show
  1. package/.claude/skills/norn-social-campaign/SKILL.md +70 -0
  2. package/CHANGELOG.md +6 -0
  3. package/demos/nornenv-region-refactor/README.md +64 -0
  4. package/dist/cli.js +360 -1
  5. package/out/apiResponseIntellisenseCache.js +394 -0
  6. package/out/assertionRunner.js +567 -0
  7. package/out/cacheDir.js +136 -0
  8. package/out/chatParticipant.js +763 -0
  9. package/out/cli/colors.js +127 -0
  10. package/out/cli/formatters/assertion.js +102 -0
  11. package/out/cli/formatters/index.js +23 -0
  12. package/out/cli/formatters/response.js +106 -0
  13. package/out/cli/formatters/summary.js +246 -0
  14. package/out/cli/redaction.js +237 -0
  15. package/out/cli/reporters/html.js +689 -0
  16. package/out/cli/reporters/index.js +22 -0
  17. package/out/cli/reporters/junit.js +226 -0
  18. package/out/codeLensProvider.js +351 -0
  19. package/out/compareContentProvider.js +85 -0
  20. package/out/completionProvider.js +3739 -0
  21. package/out/contractAssertionSummary.js +225 -0
  22. package/out/contractDecorationProvider.js +243 -0
  23. package/out/coverageCalculator.js +879 -0
  24. package/out/coveragePanel.js +597 -0
  25. package/out/debug/breakpointResolver.js +84 -0
  26. package/out/debug/breakpoints.js +52 -0
  27. package/out/debug/nornDebugAdapter.js +166 -0
  28. package/out/debug/nornDebugSession.js +613 -0
  29. package/out/debug/sequenceLocationIndex.js +77 -0
  30. package/out/debug/types.js +3 -0
  31. package/out/deepClone.js +21 -0
  32. package/out/diagnosticProvider.js +2554 -0
  33. package/out/environmentParser.js +736 -0
  34. package/out/environmentProvider.js +544 -0
  35. package/out/environmentTemplates.js +146 -0
  36. package/out/errors/formatError.js +113 -0
  37. package/out/errors/nornError.js +29 -0
  38. package/out/formUrlEncoded.js +89 -0
  39. package/out/httpClient.js +348 -0
  40. package/out/httpRuntimeOptions.js +16 -0
  41. package/out/importErrors.js +31 -0
  42. package/out/inlayHintResolver.js +70 -0
  43. package/out/jsonFileReader.js +323 -0
  44. package/out/mcpClient.js +193 -0
  45. package/out/mcpConfig.js +184 -0
  46. package/out/mcpToolIntellisenseCache.js +96 -0
  47. package/out/mcpToolSchema.js +50 -0
  48. package/out/nornConfig.js +132 -0
  49. package/out/nornHoverProvider.js +124 -0
  50. package/out/nornInlayHintsProvider.js +191 -0
  51. package/out/nornPrompt.js +755 -0
  52. package/out/nornSqlParser.js +286 -0
  53. package/out/nornapiHoverProvider.js +135 -0
  54. package/out/nornapiInlayHintsProvider.js +94 -0
  55. package/out/nornapiParser.js +324 -0
  56. package/out/nornenvCodeActionProvider.js +101 -0
  57. package/out/nornenvDecorationProvider.js +239 -0
  58. package/out/nornenvFoldingProvider.js +63 -0
  59. package/out/nornenvHoverProvider.js +114 -0
  60. package/out/nornenvInlayHintsProvider.js +99 -0
  61. package/out/nornenvLanguageModel.js +187 -0
  62. package/out/nornenvRegionRefactor.js +267 -0
  63. package/out/nornsqlHoverProvider.js +95 -0
  64. package/out/nornsqlInlayHintsProvider.js +114 -0
  65. package/out/parser.js +839 -0
  66. package/out/pathAccess.js +28 -0
  67. package/out/postmanImportPanel.js +732 -0
  68. package/out/postmanImportPlanner.js +1155 -0
  69. package/out/postmanImportSidebarView.js +532 -0
  70. package/out/quotedString.js +35 -0
  71. package/out/requestPreparation.js +179 -0
  72. package/out/requestValidation.js +146 -0
  73. package/out/responsePanel.js +7754 -0
  74. package/out/schemaGenerator.js +562 -0
  75. package/out/scriptRunner.js +419 -0
  76. package/out/secrets/cliSecrets.js +415 -0
  77. package/out/secrets/crypto.js +105 -0
  78. package/out/secrets/envFileSecrets.js +177 -0
  79. package/out/secrets/keyStore.js +259 -0
  80. package/out/sequenceDeclaration.js +15 -0
  81. package/out/sequenceRunner.js +3590 -0
  82. package/out/sqlAdapterRunner.js +122 -0
  83. package/out/sqlBuiltInAdapters.js +604 -0
  84. package/out/sqlConfig.js +184 -0
  85. package/out/starterCatalog.js +554 -0
  86. package/out/stringUtils.js +25 -0
  87. package/out/swaggerBodyIntellisenseCache.js +114 -0
  88. package/out/swaggerParser.js +464 -0
  89. package/out/testProvider.js +767 -0
  90. package/out/theoryCaseLoader.js +113 -0
  91. package/out/validationCache.js +211 -0
  92. package/package.json +6 -1
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseNornSqlFile = parseNornSqlFile;
4
+ const CONNECTION_REGEX = /^connection\s+([A-Za-z_][A-Za-z0-9_-]*)\s*$/i;
5
+ const OPERATION_REGEX = /^(query|command)\s+([A-Za-z_][A-Za-z0-9_-]*)(?:\s*\((.*)\))?\s*$/i;
6
+ const PARAMETER_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_]*$/;
7
+ function splitCommaSeparated(value) {
8
+ const parts = [];
9
+ let current = '';
10
+ for (let i = 0; i < value.length; i++) {
11
+ const char = value[i];
12
+ if (char === ',') {
13
+ parts.push(current.trim());
14
+ current = '';
15
+ continue;
16
+ }
17
+ current += char;
18
+ }
19
+ parts.push(current.trim());
20
+ return parts;
21
+ }
22
+ function parseParameterList(rawParams) {
23
+ if (rawParams === undefined) {
24
+ return { parameters: [] };
25
+ }
26
+ const trimmed = rawParams.trim();
27
+ if (!trimmed) {
28
+ return { parameters: [] };
29
+ }
30
+ const parts = splitCommaSeparated(trimmed);
31
+ const parameters = [];
32
+ const seen = new Set();
33
+ for (const part of parts) {
34
+ if (!part) {
35
+ return {
36
+ parameters: [],
37
+ error: 'Invalid parameter list syntax. Use query Name(param1, param2) or command Name(param1, param2).'
38
+ };
39
+ }
40
+ if (!PARAMETER_NAME_REGEX.test(part)) {
41
+ return {
42
+ parameters: [],
43
+ error: 'Invalid parameter list syntax. Use query Name(param1, param2) or command Name(param1, param2).'
44
+ };
45
+ }
46
+ const lower = part.toLowerCase();
47
+ if (seen.has(lower)) {
48
+ return {
49
+ parameters: [],
50
+ error: `Duplicate parameter name '${part}' in operation declaration.`
51
+ };
52
+ }
53
+ seen.add(lower);
54
+ parameters.push(part);
55
+ }
56
+ return { parameters };
57
+ }
58
+ function collectSqlPlaceholders(sql) {
59
+ const placeholders = new Set();
60
+ let inSingleQuote = false;
61
+ let inDoubleQuote = false;
62
+ let inLineComment = false;
63
+ let inBlockComment = false;
64
+ for (let i = 0; i < sql.length; i++) {
65
+ const char = sql[i];
66
+ const next = i + 1 < sql.length ? sql[i + 1] : '';
67
+ const prev = i > 0 ? sql[i - 1] : '';
68
+ if (inLineComment) {
69
+ if (char === '\n') {
70
+ inLineComment = false;
71
+ }
72
+ continue;
73
+ }
74
+ if (inBlockComment) {
75
+ if (char === '*' && next === '/') {
76
+ inBlockComment = false;
77
+ i++;
78
+ }
79
+ continue;
80
+ }
81
+ if (inSingleQuote) {
82
+ if (char === "'" && next === "'") {
83
+ i++;
84
+ continue;
85
+ }
86
+ if (char === "'") {
87
+ inSingleQuote = false;
88
+ }
89
+ continue;
90
+ }
91
+ if (inDoubleQuote) {
92
+ if (char === '"' && next === '"') {
93
+ i++;
94
+ continue;
95
+ }
96
+ if (char === '"') {
97
+ inDoubleQuote = false;
98
+ }
99
+ continue;
100
+ }
101
+ if (char === '-' && next === '-') {
102
+ inLineComment = true;
103
+ i++;
104
+ continue;
105
+ }
106
+ if (char === '/' && next === '*') {
107
+ inBlockComment = true;
108
+ i++;
109
+ continue;
110
+ }
111
+ if (char === "'") {
112
+ inSingleQuote = true;
113
+ continue;
114
+ }
115
+ if (char === '"') {
116
+ inDoubleQuote = true;
117
+ continue;
118
+ }
119
+ if (char !== ':' || next === ':' || prev === ':') {
120
+ continue;
121
+ }
122
+ if (/[A-Za-z0-9_]/.test(prev)) {
123
+ continue;
124
+ }
125
+ const match = sql.slice(i + 1).match(/^([A-Za-z_][A-Za-z0-9_]*)/);
126
+ if (!match) {
127
+ continue;
128
+ }
129
+ placeholders.add(match[1]);
130
+ i += match[1].length;
131
+ }
132
+ return Array.from(placeholders.values());
133
+ }
134
+ function validatePlaceholders(operation, errors, endLine) {
135
+ const declared = new Set(operation.parameters.map(param => param.toLowerCase()));
136
+ const placeholders = collectSqlPlaceholders(operation.bodyLines.join('\n'));
137
+ for (const placeholder of placeholders) {
138
+ if (!declared.has(placeholder.toLowerCase())) {
139
+ errors.push({
140
+ message: `Obvious SQL placeholder ':${placeholder}' does not match a declared parameter.`,
141
+ lineNumber: endLine,
142
+ blocking: true
143
+ });
144
+ }
145
+ }
146
+ }
147
+ function parseNornSqlFile(text, sourcePath) {
148
+ const lines = text.split('\n');
149
+ const operations = [];
150
+ const errors = [];
151
+ let connectionName;
152
+ let connectionLine = -1;
153
+ let currentBlock;
154
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
155
+ const rawLine = lines[lineIndex];
156
+ const trimmed = rawLine.trim();
157
+ if (currentBlock) {
158
+ if (trimmed.toLowerCase() === `end ${currentBlock.type}`) {
159
+ validatePlaceholders(currentBlock, errors, lineIndex);
160
+ operations.push({
161
+ type: currentBlock.type,
162
+ name: currentBlock.name,
163
+ parameters: currentBlock.parameters,
164
+ sql: currentBlock.bodyLines.join('\n'),
165
+ connectionName: connectionName || '',
166
+ sourcePath,
167
+ startLine: currentBlock.startLine,
168
+ endLine: lineIndex
169
+ });
170
+ currentBlock = undefined;
171
+ continue;
172
+ }
173
+ if (trimmed.toLowerCase() === 'end query' || trimmed.toLowerCase() === 'end command') {
174
+ errors.push({
175
+ message: `${trimmed.toLowerCase()} without a matching ${trimmed.toLowerCase() === 'end query' ? 'query' : 'command'}.`,
176
+ lineNumber: lineIndex,
177
+ blocking: true
178
+ });
179
+ continue;
180
+ }
181
+ currentBlock.bodyLines.push(rawLine);
182
+ continue;
183
+ }
184
+ if (!trimmed || trimmed.startsWith('#')) {
185
+ continue;
186
+ }
187
+ if (/^import\b/i.test(trimmed)) {
188
+ errors.push({
189
+ message: '`import` is not supported in `.nornsql`. Import SQL files from a `.norn` file instead.',
190
+ lineNumber: lineIndex,
191
+ blocking: true
192
+ });
193
+ continue;
194
+ }
195
+ if (/^end\s+query$/i.test(trimmed)) {
196
+ errors.push({
197
+ message: '`end query` without a matching `query`.',
198
+ lineNumber: lineIndex,
199
+ blocking: true
200
+ });
201
+ continue;
202
+ }
203
+ if (/^end\s+command$/i.test(trimmed)) {
204
+ errors.push({
205
+ message: '`end command` without a matching `command`.',
206
+ lineNumber: lineIndex,
207
+ blocking: true
208
+ });
209
+ continue;
210
+ }
211
+ const connectionMatch = trimmed.match(CONNECTION_REGEX);
212
+ if (connectionMatch) {
213
+ if (connectionName) {
214
+ errors.push({
215
+ message: 'Duplicate `connection` declaration. Each `.nornsql` file can declare only one `connection`.',
216
+ lineNumber: lineIndex,
217
+ blocking: true
218
+ });
219
+ continue;
220
+ }
221
+ connectionName = connectionMatch[1];
222
+ connectionLine = lineIndex;
223
+ continue;
224
+ }
225
+ if (/^(query|command)\b/i.test(trimmed)) {
226
+ const operationMatch = trimmed.match(OPERATION_REGEX);
227
+ if (!operationMatch) {
228
+ errors.push({
229
+ message: 'Invalid parameter list syntax. Use query Name(param1, param2) or command Name(param1, param2).',
230
+ lineNumber: lineIndex,
231
+ blocking: true
232
+ });
233
+ continue;
234
+ }
235
+ const type = operationMatch[1].toLowerCase();
236
+ const name = operationMatch[2];
237
+ const paramResult = parseParameterList(operationMatch[3]);
238
+ if (paramResult.error) {
239
+ errors.push({
240
+ message: paramResult.error,
241
+ lineNumber: lineIndex,
242
+ blocking: true
243
+ });
244
+ continue;
245
+ }
246
+ currentBlock = {
247
+ type,
248
+ name,
249
+ parameters: paramResult.parameters,
250
+ startLine: lineIndex,
251
+ bodyLines: []
252
+ };
253
+ continue;
254
+ }
255
+ errors.push({
256
+ message: 'Unknown top-level statement. Supported statements are: `connection`, `query`, `command`, `end query`, `end command`.',
257
+ lineNumber: lineIndex,
258
+ blocking: true
259
+ });
260
+ }
261
+ if (currentBlock) {
262
+ errors.push({
263
+ message: `Unterminated \`${currentBlock.type}\` block. Add \`end ${currentBlock.type}\`.`,
264
+ lineNumber: currentBlock.startLine,
265
+ blocking: true
266
+ });
267
+ }
268
+ if (!connectionName) {
269
+ errors.push({
270
+ message: 'Missing `connection` declaration. Each `.nornsql` file must declare exactly one `connection`.',
271
+ lineNumber: connectionLine >= 0 ? connectionLine : 0,
272
+ blocking: true
273
+ });
274
+ }
275
+ if (connectionName) {
276
+ for (const operation of operations) {
277
+ operation.connectionName = connectionName;
278
+ }
279
+ }
280
+ return {
281
+ connectionName,
282
+ operations,
283
+ errors
284
+ };
285
+ }
286
+ //# sourceMappingURL=nornSqlParser.js.map
@@ -0,0 +1,135 @@
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
+ exports.NornapiHoverProvider = void 0;
37
+ exports.findTemplateTokenAt = findTemplateTokenAt;
38
+ exports.renderTemplateReferenceHover = renderTemplateReferenceHover;
39
+ const vscode = __importStar(require("vscode"));
40
+ const environmentProvider_1 = require("./environmentProvider");
41
+ const environmentParser_1 = require("./environmentParser");
42
+ const inlayHintResolver_1 = require("./inlayHintResolver");
43
+ const TEMPLATE_TOKEN_REGEX = /\{\{([^{}]+)\}\}/g;
44
+ /**
45
+ * Hover over a `{{name}}` / `{{$env.name}}` token in a `.nornapi` file shows the
46
+ * resolution chain: where the variable is defined in `.nornenv`, the current resolved
47
+ * value under the active env, and a secret flag if applicable.
48
+ */
49
+ class NornapiHoverProvider {
50
+ provideHover(document, position) {
51
+ try {
52
+ const filePath = document.uri.scheme === 'file' ? document.uri.fsPath : undefined;
53
+ if (!filePath) {
54
+ return undefined;
55
+ }
56
+ const lineText = document.lineAt(position.line).text;
57
+ const tokenMatch = findTemplateTokenAt(lineText, position.character);
58
+ if (!tokenMatch) {
59
+ return undefined;
60
+ }
61
+ const parsed = (0, inlayHintResolver_1.parseInlayReference)(tokenMatch.referenceRaw);
62
+ if (!parsed) {
63
+ return undefined;
64
+ }
65
+ const config = (0, environmentProvider_1.loadEnvironmentConfig)(filePath);
66
+ if (!config) {
67
+ return undefined;
68
+ }
69
+ const activeEnvironment = (0, environmentProvider_1.getActiveEnvironment)(filePath);
70
+ const markdown = renderTemplateReferenceHover(parsed.name, config, activeEnvironment);
71
+ return new vscode.Hover(markdown, new vscode.Range(new vscode.Position(position.line, tokenMatch.tokenStart), new vscode.Position(position.line, tokenMatch.tokenEnd)));
72
+ }
73
+ catch {
74
+ return undefined;
75
+ }
76
+ }
77
+ }
78
+ exports.NornapiHoverProvider = NornapiHoverProvider;
79
+ function findTemplateTokenAt(lineText, character) {
80
+ TEMPLATE_TOKEN_REGEX.lastIndex = 0;
81
+ for (const match of lineText.matchAll(TEMPLATE_TOKEN_REGEX)) {
82
+ const start = match.index ?? 0;
83
+ const end = start + match[0].length;
84
+ if (character < start || character > end) {
85
+ continue;
86
+ }
87
+ return { referenceRaw: match[1], tokenStart: start, tokenEnd: end };
88
+ }
89
+ return undefined;
90
+ }
91
+ /**
92
+ * Builds a Markdown hover block for a `{{ref}}` resolving from the nearest `.nornenv`'s
93
+ * active environment. Shared between `.nornapi`, `.nornsql`, and `.norn` hover providers
94
+ * for the env-scope case.
95
+ */
96
+ function renderTemplateReferenceHover(name, config, activeEnvironment) {
97
+ const lines = [`**\`${name}\`**`];
98
+ if (!config) {
99
+ lines.push(`No \`.nornenv\` file found in scope.`);
100
+ return new vscode.MarkdownString(lines.join('\n\n'));
101
+ }
102
+ const secret = config.secretNames.has(name);
103
+ if (!activeEnvironment) {
104
+ if (Object.prototype.hasOwnProperty.call(config.common, name)) {
105
+ lines.push('Defined in `common`.');
106
+ lines.push(secret
107
+ ? 'No active env. Common value is a secret.'
108
+ : `No active env. Common value: \`${config.common[name]}\`.`);
109
+ }
110
+ else {
111
+ lines.push('Not defined in `common`. (No active env selected — only common vars are in scope.)');
112
+ }
113
+ return new vscode.MarkdownString(lines.join('\n\n'));
114
+ }
115
+ const details = (0, environmentParser_1.resolveEffectiveEnvVariableDetails)(activeEnvironment, config);
116
+ const detail = details.get(name);
117
+ if (!detail) {
118
+ lines.push(`Not defined in the active env \`${activeEnvironment}\` or its ancestor templates.`);
119
+ return new vscode.MarkdownString(lines.join('\n\n'));
120
+ }
121
+ const sourceLabel = detail.sourceKind === 'common'
122
+ ? 'common'
123
+ : `${detail.sourceKind}:${detail.sourceName ?? ''}`;
124
+ lines.push(`Defined in \`${sourceLabel}\`.`);
125
+ lines.push(secret
126
+ ? `Active env \`${activeEnvironment}\` resolves to a secret value.`
127
+ : `Active env \`${activeEnvironment}\` resolves to \`${detail.value}\`.`);
128
+ if (detail.inherited) {
129
+ lines.push(`Inherited by \`env:${activeEnvironment}\`.`);
130
+ }
131
+ const markdown = new vscode.MarkdownString(lines.join('\n\n'));
132
+ markdown.isTrusted = false;
133
+ return markdown;
134
+ }
135
+ //# sourceMappingURL=nornapiHoverProvider.js.map
@@ -0,0 +1,94 @@
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
+ exports.NornapiInlayHintsProvider = void 0;
37
+ const vscode = __importStar(require("vscode"));
38
+ const environmentProvider_1 = require("./environmentProvider");
39
+ const inlayHintResolver_1 = require("./inlayHintResolver");
40
+ const TEMPLATE_TOKEN_REGEX = /\{\{([^{}]+)\}\}/g;
41
+ /**
42
+ * Inlay hints for `.nornapi` files — resolves every `{{...}}` token in the file
43
+ * against the nearest `.nornenv`'s active environment. No local-var scope.
44
+ */
45
+ class NornapiInlayHintsProvider {
46
+ emitter = new vscode.EventEmitter();
47
+ environmentSubscription;
48
+ onDidChangeInlayHints = this.emitter.event;
49
+ constructor() {
50
+ this.environmentSubscription = (0, environmentProvider_1.onDidChangeActiveEnvironment)(() => {
51
+ this.emitter.fire();
52
+ });
53
+ }
54
+ provideInlayHints(document, range) {
55
+ const hints = [];
56
+ try {
57
+ const filePath = document.uri.scheme === 'file' ? document.uri.fsPath : undefined;
58
+ if (!filePath) {
59
+ return [];
60
+ }
61
+ const config = (0, environmentProvider_1.loadEnvironmentConfig)(filePath);
62
+ if (!config) {
63
+ return [];
64
+ }
65
+ const variables = (0, environmentProvider_1.getEnvironmentVariables)(filePath);
66
+ for (let lineNumber = range.start.line; lineNumber <= range.end.line; lineNumber++) {
67
+ const line = document.lineAt(lineNumber).text;
68
+ TEMPLATE_TOKEN_REGEX.lastIndex = 0;
69
+ for (const match of line.matchAll(TEMPLATE_TOKEN_REGEX)) {
70
+ const resolved = (0, inlayHintResolver_1.resolveInlayValueLabel)(match[1], variables, config.secretNames);
71
+ if (!resolved) {
72
+ continue;
73
+ }
74
+ const tokenEnd = (match.index ?? 0) + match[0].length;
75
+ const hint = new vscode.InlayHint(new vscode.Position(lineNumber, tokenEnd), resolved.label, vscode.InlayHintKind.Parameter);
76
+ hint.tooltip = resolved.secret
77
+ ? `'${match[1].trim()}' resolves from a secret value.`
78
+ : `'${match[1].trim()}' resolves to '${resolved.value}'.`;
79
+ hints.push(hint);
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ return hints;
87
+ }
88
+ dispose() {
89
+ this.environmentSubscription.dispose();
90
+ this.emitter.dispose();
91
+ }
92
+ }
93
+ exports.NornapiInlayHintsProvider = NornapiInlayHintsProvider;
94
+ //# sourceMappingURL=nornapiInlayHintsProvider.js.map