( source: string, index: number, constants: ReadonlyMap<string, string>, )
| 315 | } |
| 316 | |
| 317 | function readOptionKey( |
| 318 | source: string, |
| 319 | index: number, |
| 320 | constants: ReadonlyMap<string, string>, |
| 321 | ): { name: string | null; end: number } | null { |
| 322 | if (source[index] === "\"" || source[index] === "'" || source[index] === "`") { |
| 323 | const literal = readStringLiteral(source, index); |
| 324 | if (!literal) return null; |
| 325 | return { name: literal.value, end: literal.end }; |
| 326 | } |
| 327 | |
| 328 | if (source[index] === "[") { |
| 329 | const current = skipWhitespaceAndComments(source, index + 1); |
| 330 | const identifier = readIdentifier(source, current); |
| 331 | const end = findMatchingDelimiter(source, index, "[", "]"); |
| 332 | if (end === -1) return null; |
| 333 | const afterIdentifier = identifier |
| 334 | ? skipWhitespaceAndComments(source, identifier.end) |
| 335 | : current; |
| 336 | |
| 337 | return { |
| 338 | name: |
| 339 | identifier && afterIdentifier === end |
| 340 | ? (constants.get(identifier.value) ?? null) |
| 341 | : null, |
| 342 | end: end + 1, |
| 343 | }; |
| 344 | } |
| 345 | |
| 346 | const identifier = readIdentifier(source, index); |
| 347 | if (!identifier) return null; |
| 348 | |
| 349 | return { |
| 350 | name: identifier.value, |
| 351 | end: identifier.end, |
| 352 | }; |
| 353 | } |
| 354 | |
| 355 | function readTopLevelObjectProperties(source: string): Map<string, unknown> { |
| 356 | const properties = new Map<string, unknown>(); |
no test coverage detected