( code: string, policy: ExampleImportPolicy )
| 2523 | } |
| 2524 | |
| 2525 | function validateExampleImports( |
| 2526 | code: string, |
| 2527 | policy: ExampleImportPolicy |
| 2528 | ): ReadonlyArray<JSDocDiagnostic> { |
| 2529 | const diagnostics: Array<JSDocDiagnostic> = [] |
| 2530 | const sourceFile = ts.createSourceFile("example.ts", code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS) |
| 2531 | for (const statement of sourceFile.statements) { |
| 2532 | if (!ts.isImportDeclaration(statement) || !ts.isStringLiteralLike(statement.moduleSpecifier)) continue |
| 2533 | if (statement.importClause?.isTypeOnly) continue |
| 2534 | const source = statement.moduleSpecifier.text |
| 2535 | const namedAllowed = policy.allowedNamedBySource.get(source) |
| 2536 | const namespaceModule = policy.namespaceModuleBySource.get(source) |
| 2537 | const flatModule = policy.flatModuleBySource.get(source) |
| 2538 | const namedModule = policy.namedModuleBySource.get(source) |
| 2539 | const clause = statement.importClause |
| 2540 | if (clause === undefined) continue |
| 2541 | if (namespaceModule !== undefined) { |
| 2542 | diagnostics.push(diagnostic( |
| 2543 | "example-import-style", |
| 2544 | `JSDoc examples should use \`import { ${namespaceModule.name} } from "${namespaceModule.barrelModule}"\` instead of importing from "${source}"` |
| 2545 | )) |
| 2546 | continue |
| 2547 | } |
| 2548 | if (flatModule !== undefined) { |
| 2549 | diagnostics.push(diagnostic( |
| 2550 | "example-import-style", |
| 2551 | `JSDoc examples should import ${ |
| 2552 | Array.from(flatModule.names).map((name) => `\`${name}\``).join(", ") |
| 2553 | } from "${flatModule.barrelModule}" instead of "${source}"` |
| 2554 | )) |
| 2555 | continue |
| 2556 | } |
| 2557 | if (clause.namedBindings !== undefined && ts.isNamespaceImport(clause.namedBindings)) { |
| 2558 | if (namedAllowed !== undefined || namedModule !== undefined) { |
| 2559 | diagnostics.push(diagnostic("example-import-style", `JSDoc examples should use named imports from "${source}"`)) |
| 2560 | } |
| 2561 | continue |
| 2562 | } |
| 2563 | if (clause.name !== undefined && (namedAllowed !== undefined || namedModule !== undefined)) { |
| 2564 | diagnostics.push( |
| 2565 | diagnostic("example-import-style", `JSDoc examples should not use default imports from "${source}"`) |
| 2566 | ) |
| 2567 | } |
| 2568 | if (clause.namedBindings !== undefined && ts.isNamedImports(clause.namedBindings) && namedAllowed !== undefined) { |
| 2569 | for (const specifier of clause.namedBindings.elements) { |
| 2570 | if (specifier.isTypeOnly) continue |
| 2571 | const imported = importSpecifierName(specifier) |
| 2572 | if (!namedAllowed.has(imported)) { |
| 2573 | diagnostics.push(diagnostic( |
| 2574 | "example-import-style", |
| 2575 | `JSDoc example import \`${imported}\` from "${source}" is not a canonical public API import` |
| 2576 | )) |
| 2577 | } |
| 2578 | } |
| 2579 | } |
| 2580 | } |
| 2581 | return diagnostics |
| 2582 | } |
no test coverage detected