(description: string, characterBudget: number)
| 400 | } |
| 401 | |
| 402 | function formatFunctionDescription(description: string, characterBudget: number): string { |
| 403 | const builder = new BudgetStringBuilder(characterBudget); |
| 404 | const text = description |
| 405 | .replace(/^function [gs]et /, 'function ') |
| 406 | .replace(/^function [gs]et\(/, 'function(') |
| 407 | .replace(/^[gs]et /, ''); |
| 408 | |
| 409 | // This set of best-effort regular expressions captures common function descriptions. |
| 410 | // Ideally, some parser would provide prefix, arguments, function body text separately. |
| 411 | const asyncMatch = text.match(/^(async\s+function)/); |
| 412 | const isGenerator = text.startsWith('function*'); |
| 413 | const isGeneratorShorthand = text.startsWith('*'); |
| 414 | const isBasic = !isGenerator && text.startsWith('function'); |
| 415 | const isClass = text.startsWith('class ') || text.startsWith('class{'); |
| 416 | const firstArrowIndex = text.indexOf('=>'); |
| 417 | const isArrow = !asyncMatch && !isGenerator && !isBasic && !isClass && firstArrowIndex > 0; |
| 418 | |
| 419 | let textAfterPrefix: string; |
| 420 | if (isClass) { |
| 421 | textAfterPrefix = text.substring('class'.length); |
| 422 | const classNameMatch = /^[^{\s]+/.exec(textAfterPrefix.trim()); |
| 423 | let className = ''; |
| 424 | if (classNameMatch) className = classNameMatch[0].trim() || ''; |
| 425 | addToken('class', textAfterPrefix, className); |
| 426 | } else if (asyncMatch) { |
| 427 | textAfterPrefix = text.substring(asyncMatch[1].length); |
| 428 | addToken('async ƒ', textAfterPrefix, nameAndArguments(textAfterPrefix)); |
| 429 | } else if (isGenerator) { |
| 430 | textAfterPrefix = text.substring('function*'.length); |
| 431 | addToken('ƒ*', textAfterPrefix, nameAndArguments(textAfterPrefix)); |
| 432 | } else if (isGeneratorShorthand) { |
| 433 | textAfterPrefix = text.substring('*'.length); |
| 434 | addToken('ƒ*', textAfterPrefix, nameAndArguments(textAfterPrefix)); |
| 435 | } else if (isBasic) { |
| 436 | textAfterPrefix = text.substring('function'.length); |
| 437 | addToken('ƒ', textAfterPrefix, nameAndArguments(textAfterPrefix)); |
| 438 | } else if (isArrow) { |
| 439 | let abbreviation = text; |
| 440 | if (text.length > maxArrowFunctionCharacterLength) { |
| 441 | abbreviation = text.substring(0, firstArrowIndex + 2) + ' {\u2026}'; |
| 442 | } |
| 443 | addToken('', text, abbreviation); |
| 444 | } else { |
| 445 | addToken('ƒ', text, nameAndArguments(text)); |
| 446 | } |
| 447 | return builder.build(); |
| 448 | |
| 449 | function nameAndArguments(contents: string): string { |
| 450 | const startOfArgumentsIndex = contents.indexOf('('); |
| 451 | const endOfArgumentsMatch = contents.match(/\)\s*{/); |
| 452 | const endIndex = (endOfArgumentsMatch && endOfArgumentsMatch.index) || 0; |
| 453 | if (startOfArgumentsIndex !== -1 && endOfArgumentsMatch && endIndex > startOfArgumentsIndex) { |
| 454 | const name = contents.substring(0, startOfArgumentsIndex).trim() || ''; |
| 455 | const args = contents.substring(startOfArgumentsIndex, endIndex + 1); |
| 456 | return name + args; |
| 457 | } |
| 458 | return '()'; |
| 459 | } |
no test coverage detected