UNPKG

@angular/compiler-cli

Version:
1,308 lines (1,280 loc) • 223 kB
import {createRequire as __cjsCompatRequire} from 'module'; const require = __cjsCompatRequire(import.meta.url); import { angularJitApplicationTransform } from "./chunk-6SNDDF7J.js"; import { AbsoluteModuleStrategy, ActivePerfRecorder, AliasStrategy, COMPILER_ERRORS_WITH_GUIDES, CompilationMode, ComponentDecoratorHandler, ComponentScopeKind, CompoundComponentScopeReader, CompoundMetadataReader, CompoundMetadataRegistry, DefaultImportTracker, DeferredSymbolTracker, DelegatingPerfRecorder, DirectiveDecoratorHandler, DtsMetadataReader, DtsTransformRegistry, ERROR_DETAILS_PAGE_BASE_URL, ErrorCode, ExportedProviderStatusResolver, ExtendedTemplateDiagnosticName, HostDirectivesResolver, INPUT_INITIALIZER_FN, ImportedSymbolsTracker, InjectableClassRegistry, InjectableDecoratorHandler, JitDeclarationRegistry, LocalCompilationExtraImportsTracker, LocalIdentifierStrategy, LocalMetadataRegistry, LocalModuleScopeRegistry, LogicalProjectStrategy, MODEL_INITIALIZER_FN, MetaKind, MetadataDtsModuleScopeResolver, ModuleResolver, NgModuleDecoratorHandler, NgOriginalFile, NoopImportRewriter, NoopReferencesRegistry, OUTPUT_INITIALIZER_FNS, OptimizeFor, PartialEvaluator, PerfCheckpoint, PerfEvent, PerfPhase, PipeDecoratorHandler, PrivateExportAliasingHost, QUERY_INITIALIZER_FNS, R3SymbolsImportRewriter, Reference, ReferenceEmitter, RelativePathStrategy, ResourceRegistry, SelectorlessComponentScopeReader, SemanticDepGraphUpdater, ShimAdapter, ShimReferenceTagger, SymbolKind, TemplateTypeCheckerImpl, TraitCompiler, TsCreateProgramDriver, TypeCheckScopeRegistry, TypeCheckShimGenerator, TypeScriptReflectionHost, UnifiedModulesAliasingHost, UnifiedModulesStrategy, aliasTransformFactory, declarationTransformFactory, getRootDirs, getSourceFileOrNull, isDtsPath, isFatalDiagnosticError, isNamedClassDeclaration, isNonDeclarationTsPath, isShim, ivyTransformFactory, makeDiagnostic, ngErrorCode, normalizeSeparators, relativePathBetween, replaceTsWithNgInErrors, retagAllTsFiles, signalMetadataTransform, toUnredirectedSourceFile, tryParseInitializerApi, untagAllTsFiles } from "./chunk-RO5VAPEI.js"; import { LogicalFileSystem, absoluteFrom, absoluteFromSourceFile, createFileSystemTsReadDirectoryFn, dirname, getFileSystem, join, resolve } from "./chunk-GWZQLAGK.js"; // packages/compiler-cli/src/transformers/api.js var DEFAULT_ERROR_CODE = 100; var UNKNOWN_ERROR_CODE = 500; var SOURCE = "angular"; function isTsDiagnostic(diagnostic) { return diagnostic != null && diagnostic.source !== "angular"; } var EmitFlags; (function(EmitFlags2) { EmitFlags2[EmitFlags2["DTS"] = 1] = "DTS"; EmitFlags2[EmitFlags2["JS"] = 2] = "JS"; EmitFlags2[EmitFlags2["Metadata"] = 4] = "Metadata"; EmitFlags2[EmitFlags2["I18nBundle"] = 8] = "I18nBundle"; EmitFlags2[EmitFlags2["Codegen"] = 16] = "Codegen"; EmitFlags2[EmitFlags2["Default"] = 19] = "Default"; EmitFlags2[EmitFlags2["All"] = 31] = "All"; })(EmitFlags || (EmitFlags = {})); // packages/compiler-cli/src/transformers/compiler_host.js import ts from "typescript"; var wrapHostForTest = null; function createCompilerHost({ options, tsHost = ts.createCompilerHost(options, true) }) { if (wrapHostForTest !== null) { tsHost = wrapHostForTest(tsHost); } return tsHost; } // packages/compiler-cli/src/ngtsc/docs/src/entities.js var EntryType; (function(EntryType2) { EntryType2["Block"] = "block"; EntryType2["Component"] = "component"; EntryType2["Constant"] = "constant"; EntryType2["Decorator"] = "decorator"; EntryType2["Directive"] = "directive"; EntryType2["Element"] = "element"; EntryType2["Enum"] = "enum"; EntryType2["Function"] = "function"; EntryType2["Interface"] = "interface"; EntryType2["NgModule"] = "ng_module"; EntryType2["Pipe"] = "pipe"; EntryType2["TypeAlias"] = "type_alias"; EntryType2["UndecoratedClass"] = "undecorated_class"; EntryType2["InitializerApiFunction"] = "initializer_api_function"; })(EntryType || (EntryType = {})); var MemberType; (function(MemberType2) { MemberType2["Property"] = "property"; MemberType2["Method"] = "method"; MemberType2["Getter"] = "getter"; MemberType2["Setter"] = "setter"; MemberType2["EnumItem"] = "enum_item"; })(MemberType || (MemberType = {})); var DecoratorType; (function(DecoratorType2) { DecoratorType2["Class"] = "class"; DecoratorType2["Member"] = "member"; DecoratorType2["Parameter"] = "parameter"; })(DecoratorType || (DecoratorType = {})); var MemberTags; (function(MemberTags2) { MemberTags2["Abstract"] = "abstract"; MemberTags2["Static"] = "static"; MemberTags2["Readonly"] = "readonly"; MemberTags2["Protected"] = "protected"; MemberTags2["Optional"] = "optional"; MemberTags2["Input"] = "input"; MemberTags2["Output"] = "output"; MemberTags2["Inherited"] = "override"; })(MemberTags || (MemberTags = {})); function isDocEntryWithSourceInfo(entry) { return "source" in entry; } // packages/compiler-cli/src/ngtsc/docs/src/extractor.js import ts12 from "typescript"; // packages/compiler-cli/src/ngtsc/docs/src/class_extractor.js import ts6 from "typescript"; // packages/compiler-cli/src/ngtsc/docs/src/filters.js function isAngularPrivateName(name) { const firstChar = name[0] ?? ""; return firstChar === "\u0275" || firstChar === "_"; } // packages/compiler-cli/src/ngtsc/docs/src/function_extractor.js import ts4 from "typescript"; // packages/compiler-cli/src/ngtsc/docs/src/generics_extractor.js function extractGenerics(declaration) { return declaration.typeParameters?.map((typeParam) => ({ name: typeParam.name.getText(), constraint: typeParam.constraint?.getText(), default: typeParam.default?.getText() })) ?? []; } // packages/compiler-cli/src/ngtsc/docs/src/jsdoc_extractor.js import ts2 from "typescript"; var decoratorExpression = /@(?=(Injectable|Component|Directive|Pipe|NgModule|Input|Output|HostBinding|HostListener|Inject|Optional|Self|Host|SkipSelf|ViewChild|ViewChildren|ContentChild|ContentChildren))/g; function extractJsDocTags(node) { const escapedNode = getEscapedNode(node); return ts2.getJSDocTags(escapedNode).map((t) => { return { name: t.tagName.getText(), comment: unescapeAngularDecorators(ts2.getTextOfJSDocComment(t.comment) ?? "") }; }); } function extractJsDocDescription(node) { const escapedNode = getEscapedNode(node); const commentOrTag = ts2.getJSDocCommentsAndTags(escapedNode).find((d) => { return ts2.isJSDoc(d) || ts2.isJSDocParameterTag(d); }); const comment = commentOrTag?.comment ?? ""; const description = typeof comment === "string" ? comment : ts2.getTextOfJSDocComment(comment) ?? ""; return unescapeAngularDecorators(description); } function extractRawJsDoc(node) { const comment = ts2.getJSDocCommentsAndTags(node).find(ts2.isJSDoc)?.getFullText() ?? ""; return unescapeAngularDecorators(comment); } function getEscapedNode(node) { if (ts2.isParameter(node)) { return node; } const rawComment = extractRawJsDoc(node); const escaped = escapeAngularDecorators(rawComment); const file = ts2.createSourceFile("x.ts", `${escaped}class X {}`, ts2.ScriptTarget.ES2020, true); return file.statements.find((s) => ts2.isClassDeclaration(s)); } function escapeAngularDecorators(comment) { return comment.replace(decoratorExpression, "_NG_AT_"); } function unescapeAngularDecorators(comment) { return comment.replace(/_NG_AT_/g, "@"); } // packages/compiler-cli/src/ngtsc/docs/src/type_extractor.js import ts3 from "typescript"; function extractResolvedTypeString(node, checker) { return checker.typeToString(checker.getTypeAtLocation(node), void 0, ts3.TypeFormatFlags.NoTruncation); } // packages/compiler-cli/src/ngtsc/docs/src/function_extractor.js var FunctionExtractor = class { name; exportDeclaration; typeChecker; constructor(name, exportDeclaration, typeChecker) { this.name = name; this.exportDeclaration = exportDeclaration; this.typeChecker = typeChecker; } extract() { const signature = this.typeChecker.getSignatureFromDeclaration(this.exportDeclaration); const returnType = signature ? extractReturnType(signature, this.typeChecker) : "unknown"; const implementation = findImplementationOfFunction(this.exportDeclaration, this.typeChecker) ?? this.exportDeclaration; const type = this.typeChecker.getTypeAtLocation(this.exportDeclaration); const overloads = ts4.isConstructorDeclaration(this.exportDeclaration) ? constructorOverloads(this.exportDeclaration, this.typeChecker) : extractCallSignatures(this.name, this.typeChecker, type); const jsdocsTags = extractJsDocTags(implementation); const description = extractJsDocDescription(implementation); return { name: this.name, signatures: overloads, implementation: { params: extractAllParams(implementation.parameters, this.typeChecker), isNewType: ts4.isConstructSignatureDeclaration(implementation), returnType, returnDescription: jsdocsTags.find((tag) => tag.name === "returns")?.comment, generics: extractGenerics(implementation), name: this.name, description, entryType: EntryType.Function, jsdocTags: jsdocsTags, rawComment: extractRawJsDoc(implementation) }, entryType: EntryType.Function, description, jsdocTags: jsdocsTags, rawComment: extractRawJsDoc(implementation) }; } }; function constructorOverloads(constructorDeclaration, typeChecker) { const classDeclaration = constructorDeclaration.parent; const constructorNode = classDeclaration.members.filter((member) => { return ts4.isConstructorDeclaration(member) && !member.body; }); return constructorNode.map((n) => { return { name: "constructor", params: extractAllParams(n.parameters, typeChecker), returnType: typeChecker.getTypeAtLocation(classDeclaration)?.symbol.name, description: extractJsDocDescription(n), entryType: EntryType.Function, jsdocTags: extractJsDocTags(n), rawComment: extractRawJsDoc(n), generics: extractGenerics(n), isNewType: false }; }); } function extractAllParams(params, typeChecker) { return params.map((param) => ({ name: param.name.getText(), description: extractJsDocDescription(param), type: extractResolvedTypeString(param, typeChecker), isOptional: !!(param.questionToken || param.initializer), isRestParam: !!param.dotDotDotToken })); } function filterSignatureDeclarations(signatures) { const result = []; for (const signature of signatures) { const decl = signature.getDeclaration(); if (ts4.isFunctionDeclaration(decl) || ts4.isCallSignatureDeclaration(decl) || ts4.isMethodDeclaration(decl) || ts4.isConstructSignatureDeclaration(decl)) { result.push({ signature, decl }); } } return result; } function extractCallSignatures(name, typeChecker, type) { return filterSignatureDeclarations(type.getCallSignatures()).map(({ decl, signature }) => ({ name, entryType: EntryType.Function, description: extractJsDocDescription(decl), generics: extractGenerics(decl), isNewType: false, jsdocTags: extractJsDocTags(decl), params: extractAllParams(decl.parameters, typeChecker), rawComment: extractRawJsDoc(decl), returnType: extractReturnType(signature, typeChecker) })); } function extractReturnType(signature, typeChecker) { if (signature?.declaration?.type && ts4.isTypePredicateNode(signature.declaration.type)) { return signature.declaration.type.getText(); } return typeChecker.typeToString( typeChecker.getReturnTypeOfSignature(signature), void 0, // This ensures that e.g. `T | undefined` is not reduced to `T`. ts4.TypeFormatFlags.NoTypeReduction | ts4.TypeFormatFlags.NoTruncation ); } function findImplementationOfFunction(node, typeChecker) { if (node.body !== void 0 || node.name === void 0) { return node; } const symbol = typeChecker.getSymbolAtLocation(node.name); const implementation = symbol?.declarations?.find((s) => ts4.isFunctionDeclaration(s) && s.body !== void 0); return implementation; } // packages/compiler-cli/src/ngtsc/docs/src/internal.js import ts5 from "typescript"; function isInternal(member) { return extractJsDocTags(member).some((tag) => tag.name === "internal") || hasLeadingInternalComment(member); } function hasLeadingInternalComment(member) { const memberText = member.getSourceFile().text; return ts5.reduceEachLeadingCommentRange( memberText, member.getFullStart(), (pos, end, kind, hasTrailingNewLine, containsInternal) => { return containsInternal || memberText.slice(pos, end).includes("@internal"); }, /* state */ false, /* initial */ false ) ?? false; } // packages/compiler-cli/src/ngtsc/docs/src/class_extractor.js var ClassExtractor = class { declaration; typeChecker; constructor(declaration, typeChecker) { this.declaration = declaration; this.typeChecker = typeChecker; } /** Extract docs info specific to classes. */ extract() { return { name: this.declaration.name.text, isAbstract: this.isAbstract(), entryType: ts6.isInterfaceDeclaration(this.declaration) ? EntryType.Interface : EntryType.UndecoratedClass, members: this.extractSignatures().concat(this.extractAllClassMembers()), generics: extractGenerics(this.declaration), description: extractJsDocDescription(this.declaration), jsdocTags: extractJsDocTags(this.declaration), rawComment: extractRawJsDoc(this.declaration), extends: this.extractInheritance(this.declaration), implements: this.extractInterfaceConformance(this.declaration) }; } /** Extracts doc info for a class's members. */ extractAllClassMembers() { const members = []; for (const member of this.getMemberDeclarations()) { if (this.isMemberExcluded(member)) continue; const memberEntry = this.extractClassMember(member); if (memberEntry) { members.push(memberEntry); } } return members; } /** Extract docs for a class's members (methods and properties). */ extractClassMember(memberDeclaration) { if (this.isMethod(memberDeclaration)) { return this.extractMethod(memberDeclaration); } else if (this.isProperty(memberDeclaration) && !this.hasPrivateComputedProperty(memberDeclaration)) { return this.extractClassProperty(memberDeclaration); } else if (ts6.isAccessor(memberDeclaration)) { return this.extractGetterSetter(memberDeclaration); } else if (ts6.isConstructorDeclaration(memberDeclaration) && memberDeclaration.parameters.length > 0) { return this.extractConstructor(memberDeclaration); } return void 0; } /** Extract docs for all call signatures in the current class/interface. */ extractSignatures() { return this.computeAllSignatureDeclarations().map((s) => this.extractSignature(s)); } /** Extracts docs for a class method. */ extractMethod(methodDeclaration) { const functionExtractor = new FunctionExtractor(methodDeclaration.name.getText(), methodDeclaration, this.typeChecker); return { ...functionExtractor.extract(), memberType: MemberType.Method, memberTags: this.getMemberTags(methodDeclaration) }; } /** Extracts docs for a signature element (usually inside an interface). */ extractSignature(signature) { const functionExtractor = new FunctionExtractor(ts6.isConstructSignatureDeclaration(signature) ? "new" : "", signature, this.typeChecker); return { ...functionExtractor.extract(), memberType: MemberType.Method, memberTags: [] }; } /** Extracts doc info for a property declaration. */ extractClassProperty(propertyDeclaration) { return { name: propertyDeclaration.name.getText(), type: extractResolvedTypeString(propertyDeclaration, this.typeChecker), memberType: MemberType.Property, memberTags: this.getMemberTags(propertyDeclaration), description: extractJsDocDescription(propertyDeclaration), jsdocTags: extractJsDocTags(propertyDeclaration) }; } /** Extracts doc info for an accessor member (getter/setter). */ extractGetterSetter(accessor) { return { ...this.extractClassProperty(accessor), memberType: ts6.isGetAccessor(accessor) ? MemberType.Getter : MemberType.Setter }; } extractConstructor(constructorDeclaration) { const functionExtractor = new FunctionExtractor("constructor", constructorDeclaration, this.typeChecker); return { ...functionExtractor.extract(), memberType: MemberType.Method, memberTags: this.getMemberTags(constructorDeclaration) }; } extractInheritance(declaration) { if (!declaration.heritageClauses) { return void 0; } for (const clause of declaration.heritageClauses) { if (clause.token === ts6.SyntaxKind.ExtendsKeyword) { const types = clause.types; if (types.length > 0) { const baseClass = types[0]; return baseClass.getText(); } } } return void 0; } extractInterfaceConformance(declaration) { const implementClause = declaration.heritageClauses?.find((clause) => clause.token === ts6.SyntaxKind.ImplementsKeyword); return implementClause?.types.map((m) => m.getText()) ?? []; } /** Gets the tags for a member (protected, readonly, static, etc.) */ getMemberTags(member) { const tags = this.getMemberTagsFromModifiers(member.modifiers ?? []); if (member.questionToken) { tags.push(MemberTags.Optional); } if (member.parent !== this.declaration) { tags.push(MemberTags.Inherited); } return tags; } /** Computes all signature declarations of the class/interface. */ computeAllSignatureDeclarations() { const type = this.typeChecker.getTypeAtLocation(this.declaration); const signatures = [...type.getCallSignatures(), ...type.getConstructSignatures()]; const result = []; for (const signature of signatures) { const decl = signature.getDeclaration(); if (this.isDocumentableSignature(decl) && this.isDocumentableMember(decl)) { result.push(decl); } } return result; } /** Gets all member declarations, including inherited members. */ getMemberDeclarations() { const type = this.typeChecker.getTypeAtLocation(this.declaration); const members = type.getProperties(); const constructor = type.getSymbol()?.members?.get(ts6.InternalSymbolName.Constructor); const typeOfConstructor = this.typeChecker.getTypeOfSymbol(type.symbol); const staticMembers = typeOfConstructor.getProperties(); const result = []; for (const member of [...constructor ? [constructor] : [], ...members, ...staticMembers]) { const memberDeclarations = this.filterMethodOverloads(member.getDeclarations() ?? []); for (const memberDeclaration of memberDeclarations) { if (this.isDocumentableMember(memberDeclaration)) { result.push(memberDeclaration); } } } return result; } /** The result only contains properties, method implementations and abstracts */ filterMethodOverloads(declarations) { return declarations.filter((declaration, index) => { if (ts6.isFunctionDeclaration(declaration) || ts6.isMethodDeclaration(declaration) || ts6.isConstructorDeclaration(declaration)) { const nextDeclaration = declarations[index + 1]; const isNextMethodWithSameName = nextDeclaration && (ts6.isMethodDeclaration(nextDeclaration) && nextDeclaration.name.getText() === declaration.name?.getText() || ts6.isConstructorDeclaration(nextDeclaration) && ts6.isConstructorDeclaration(declaration)); return !isNextMethodWithSameName; } return true; }); } /** Get the tags for a member that come from the declaration modifiers. */ getMemberTagsFromModifiers(mods) { const tags = []; for (const mod of mods) { const tag = this.getTagForMemberModifier(mod); if (tag) tags.push(tag); } return tags; } /** Gets the doc tag corresponding to a class member modifier (readonly, protected, etc.). */ getTagForMemberModifier(mod) { switch (mod.kind) { case ts6.SyntaxKind.StaticKeyword: return MemberTags.Static; case ts6.SyntaxKind.ReadonlyKeyword: return MemberTags.Readonly; case ts6.SyntaxKind.ProtectedKeyword: return MemberTags.Protected; case ts6.SyntaxKind.AbstractKeyword: return MemberTags.Abstract; default: return void 0; } } /** * Gets whether a given class member should be excluded from public API docs. * This is the case if: * - The member does not have a name * - The member is neither a method nor property * - The member is private * - The member has a name that marks it as Angular-internal. * - The member is marked as internal via JSDoc. */ isMemberExcluded(member) { if (ts6.isConstructorDeclaration(member)) { return false; } return !member.name || !this.isDocumentableMember(member) || !ts6.isCallSignatureDeclaration(member) && member.modifiers?.some((mod) => mod.kind === ts6.SyntaxKind.PrivateKeyword) || member.name.getText() === "prototype" || isAngularPrivateName(member.name.getText()) || isInternal(member); } /** Gets whether a class member is a method, property, or accessor. */ isDocumentableMember(member) { return this.isMethod(member) || this.isProperty(member) || ts6.isAccessor(member) || ts6.isConstructorDeclaration(member) || // Signatures are documentable if they are part of an interface. ts6.isCallSignatureDeclaration(member); } /** Check if the parameter is a constructor parameter with a public modifier */ isPublicConstructorParameterProperty(node) { if (ts6.isParameterPropertyDeclaration(node, node.parent) && node.modifiers) { return node.modifiers.some((modifier) => modifier.kind === ts6.SyntaxKind.PublicKeyword); } return false; } /** Gets whether a member is a property. */ isProperty(member) { return ts6.isPropertyDeclaration(member) || ts6.isPropertySignature(member) || this.isPublicConstructorParameterProperty(member); } /** Gets whether a member is a method. */ isMethod(member) { return ts6.isMethodDeclaration(member) || ts6.isMethodSignature(member); } /** Gets whether the given signature declaration is documentable. */ isDocumentableSignature(signature) { return ts6.isConstructSignatureDeclaration(signature) || ts6.isCallSignatureDeclaration(signature); } /** Gets whether the declaration for this extractor is abstract. */ isAbstract() { const modifiers = this.declaration.modifiers ?? []; return modifiers.some((mod) => mod.kind === ts6.SyntaxKind.AbstractKeyword); } /** * Check wether a member has a private computed property name like [ɵWRITABLE_SIGNAL] * * This will prevent exposing private computed properties in the docs. */ hasPrivateComputedProperty(property) { return ts6.isComputedPropertyName(property.name) && property.name.expression.getText().startsWith("\u0275"); } }; var DirectiveExtractor = class extends ClassExtractor { reference; metadata; constructor(declaration, reference, metadata, checker) { super(declaration, checker); this.reference = reference; this.metadata = metadata; } /** Extract docs info for directives and components (including underlying class info). */ extract() { return { ...super.extract(), isStandalone: this.metadata.isStandalone, selector: this.metadata.selector ?? "", exportAs: this.metadata.exportAs ?? [], entryType: this.metadata.isComponent ? EntryType.Component : EntryType.Directive }; } /** Extracts docs info for a directive property, including input/output metadata. */ extractClassProperty(propertyDeclaration) { const entry = super.extractClassProperty(propertyDeclaration); const inputMetadata = this.getInputMetadata(propertyDeclaration); if (inputMetadata) { entry.memberTags.push(MemberTags.Input); entry.inputAlias = inputMetadata.bindingPropertyName; entry.isRequiredInput = inputMetadata.required; } const outputMetadata = this.getOutputMetadata(propertyDeclaration); if (outputMetadata) { entry.memberTags.push(MemberTags.Output); entry.outputAlias = outputMetadata.bindingPropertyName; } return entry; } /** Gets the input metadata for a directive property. */ getInputMetadata(prop) { const propName = prop.name.getText(); return this.metadata.inputs?.getByClassPropertyName(propName) ?? void 0; } /** Gets the output metadata for a directive property. */ getOutputMetadata(prop) { const propName = prop.name.getText(); return this.metadata?.outputs?.getByClassPropertyName(propName) ?? void 0; } }; var PipeExtractor = class extends ClassExtractor { reference; metadata; constructor(declaration, reference, metadata, typeChecker) { super(declaration, typeChecker); this.reference = reference; this.metadata = metadata; } extract() { return { ...super.extract(), pipeName: this.metadata.name, entryType: EntryType.Pipe, isStandalone: this.metadata.isStandalone, usage: extractPipeSyntax(this.metadata, this.declaration), isPure: this.metadata.isPure }; } }; var NgModuleExtractor = class extends ClassExtractor { reference; metadata; constructor(declaration, reference, metadata, typeChecker) { super(declaration, typeChecker); this.reference = reference; this.metadata = metadata; } extract() { return { ...super.extract(), entryType: EntryType.NgModule }; } }; function extractClass(classDeclaration, metadataReader, typeChecker) { const ref = new Reference(classDeclaration); let extractor; let directiveMetadata = metadataReader.getDirectiveMetadata(ref); let pipeMetadata = metadataReader.getPipeMetadata(ref); let ngModuleMetadata = metadataReader.getNgModuleMetadata(ref); if (directiveMetadata) { extractor = new DirectiveExtractor(classDeclaration, ref, directiveMetadata, typeChecker); } else if (pipeMetadata) { extractor = new PipeExtractor(classDeclaration, ref, pipeMetadata, typeChecker); } else if (ngModuleMetadata) { extractor = new NgModuleExtractor(classDeclaration, ref, ngModuleMetadata, typeChecker); } else { extractor = new ClassExtractor(classDeclaration, typeChecker); } return extractor.extract(); } function extractInterface(declaration, typeChecker) { const extractor = new ClassExtractor(declaration, typeChecker); return extractor.extract(); } function extractPipeSyntax(metadata, classDeclaration) { const transformParams = classDeclaration.members.find((member) => { return ts6.isMethodDeclaration(member) && member.name && ts6.isIdentifier(member.name) && member.name.getText() === "transform"; }); let paramNames = transformParams.parameters.slice(1).map((param) => { return param.name.getText(); }); return `{{ value_expression | ${metadata.name}${paramNames.length ? ":" + paramNames.join(":") : ""} }}`; } // packages/compiler-cli/src/ngtsc/docs/src/constant_extractor.js import ts7 from "typescript"; var LITERAL_AS_ENUM_TAG = "object-literal-as-enum"; function extractConstant(declaration, typeChecker) { const resolvedType = typeChecker.getBaseTypeOfLiteralType(typeChecker.getTypeAtLocation(declaration)); const rawComment = extractRawJsDoc(declaration.parent.parent); const jsdocTags = extractJsDocTags(declaration); const description = extractJsDocDescription(declaration); const name = declaration.name.getText(); if (jsdocTags.some((tag) => tag.name === LITERAL_AS_ENUM_TAG)) { return { name, entryType: EntryType.Enum, members: extractLiteralPropertiesAsEnumMembers(declaration), rawComment, description, jsdocTags: jsdocTags.filter((tag) => tag.name !== LITERAL_AS_ENUM_TAG) }; } return { name, type: typeChecker.typeToString(resolvedType), entryType: EntryType.Constant, rawComment, description, jsdocTags }; } function isSyntheticAngularConstant(declaration) { return declaration.name.getText() === "USED_FOR_NG_TYPE_CHECKING"; } function extractLiteralPropertiesAsEnumMembers(declaration) { let initializer = declaration.initializer; while (initializer && (ts7.isAsExpression(initializer) || ts7.isParenthesizedExpression(initializer))) { initializer = initializer.expression; } if (initializer === void 0 || !ts7.isObjectLiteralExpression(initializer)) { throw new Error(`Declaration tagged with "${LITERAL_AS_ENUM_TAG}" must be initialized to an object literal, but received ${initializer ? ts7.SyntaxKind[initializer.kind] : "undefined"}`); } return initializer.properties.map((prop) => { if (!ts7.isPropertyAssignment(prop) || !ts7.isIdentifier(prop.name)) { throw new Error(`Property in declaration tagged with "${LITERAL_AS_ENUM_TAG}" must be a property assignment with a static name`); } if (!ts7.isNumericLiteral(prop.initializer) && !ts7.isStringLiteralLike(prop.initializer)) { throw new Error(`Property in declaration tagged with "${LITERAL_AS_ENUM_TAG}" must be initialized to a number or string literal`); } return { name: prop.name.text, type: `${declaration.name.getText()}.${prop.name.text}`, value: prop.initializer.getText(), memberType: MemberType.EnumItem, jsdocTags: extractJsDocTags(prop), description: extractJsDocDescription(prop), memberTags: [] }; }); } // packages/compiler-cli/src/ngtsc/docs/src/decorator_extractor.js import ts8 from "typescript"; function extractorDecorator(declaration, typeChecker) { const documentedNode = getDecoratorJsDocNode(declaration, typeChecker); const decoratorType = getDecoratorType(declaration); if (!decoratorType) { throw new Error(`"${declaration.name.getText()} is not a decorator."`); } const members = getDecoratorProperties(declaration, typeChecker); let signatures = []; if (!members) { const decoratorInterface = getDecoratorDeclaration(declaration, typeChecker); const callSignatures = decoratorInterface.members.filter(ts8.isCallSignatureDeclaration); signatures = getDecoratorSignatures(callSignatures, typeChecker); } return { name: declaration.name.getText(), decoratorType, entryType: EntryType.Decorator, rawComment: extractRawJsDoc(documentedNode), description: extractJsDocDescription(documentedNode), jsdocTags: extractJsDocTags(documentedNode), members, signatures }; } function isDecoratorDeclaration(declaration) { return !!getDecoratorType(declaration); } function isDecoratorOptionsInterface(declaration) { return declaration.getSourceFile().statements.some((s) => ts8.isVariableStatement(s) && s.declarationList.declarations.some((d) => isDecoratorDeclaration(d) && d.name.getText() === declaration.name.getText())); } function getDecoratorType(declaration) { const initializer = declaration.initializer?.getFullText() ?? ""; if (initializer.includes("makeDecorator")) return DecoratorType.Class; if (initializer.includes("makePropDecorator")) return DecoratorType.Member; if (initializer.includes("makeParamDecorator")) return DecoratorType.Parameter; return void 0; } function getDecoratorDeclaration(declaration, typeChecker) { const decoratorName = declaration.name.getText(); const decoratorDeclaration = declaration; const decoratorType = typeChecker.getTypeAtLocation(decoratorDeclaration); const aliasDeclaration = decoratorType.getSymbol().getDeclarations()[0]; const decoratorInterface = aliasDeclaration; if (!decoratorInterface || !ts8.isInterfaceDeclaration(decoratorInterface)) { throw new Error(`No decorator interface found for "${decoratorName}".`); } return decoratorInterface; } function getDecoratorProperties(declaration, typeChecker) { const decoratorCallSig = getDecoratorJsDocNode(declaration, typeChecker); const decoratorFirstParam = decoratorCallSig.parameters[0]; const firstParamType = typeChecker.getTypeAtLocation(decoratorFirstParam); let firstParamTypeDecl; if (firstParamType.isUnion()) { const firstParamTypeUnion = firstParamType.types.find((t) => (t.flags & ts8.TypeFlags.Undefined) === 0); firstParamTypeDecl = firstParamTypeUnion?.getSymbol()?.getDeclarations()[0]; } else { firstParamTypeDecl = firstParamType.getSymbol()?.getDeclarations()[0]; } if (!firstParamTypeDecl || !ts8.isInterfaceDeclaration(firstParamTypeDecl)) { return null; } const interfaceDeclaration = firstParamTypeDecl; return extractInterface(interfaceDeclaration, typeChecker).members; } function getDecoratorSignatures(callSignatures, typeChecker) { return callSignatures.map((signatureDecl) => { return { parameters: extractParams(signatureDecl.parameters, typeChecker), jsdocTags: extractJsDocTags(signatureDecl) }; }); } function extractParams(params, typeChecker) { return params.map((param) => ({ name: param.name.getText(), description: extractJsDocDescription(param), type: getParamTypeString(param, typeChecker), isOptional: !!(param.questionToken || param.initializer), isRestParam: !!param.dotDotDotToken })); } function getDecoratorInterface(declaration, typeChecker) { const name = declaration.name.getText(); const symbol = typeChecker.getSymbolAtLocation(declaration.name); const decoratorType = typeChecker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration); const decoratorInterface = decoratorType.getSymbol()?.getDeclarations()[0]; if (!decoratorInterface || !ts8.isInterfaceDeclaration(decoratorInterface)) { throw new Error(`No decorator interface found for "${name}".`); } return decoratorInterface; } function getDecoratorJsDocNode(declaration, typeChecker) { const name = declaration.name.getText(); const decoratorInterface = getDecoratorInterface(declaration, typeChecker); const callSignature = decoratorInterface.members.filter((node) => { return ts8.isCallSignatureDeclaration(node) && extractRawJsDoc(node); }).at(-1); if (!callSignature || !ts8.isCallSignatureDeclaration(callSignature)) { throw new Error(`No call signature with JsDoc on "${name}Decorator"`); } return callSignature; } function getParamTypeString(paramNode, typeChecker) { const type = typeChecker.getTypeAtLocation(paramNode); const printer = ts8.createPrinter({ removeComments: true }); const sourceFile = paramNode.getSourceFile(); const replace = []; if (type.isUnion()) { for (const subType of type.types) { const decl = subType.getSymbol()?.getDeclarations()?.[0]; if (decl && ts8.isInterfaceDeclaration(decl) && decl.name.text !== "Function") { replace.push({ initial: subType.symbol.name, replacedWith: expandType(decl, sourceFile, printer) }); } } } let result = printer.printNode(ts8.EmitHint.Unspecified, paramNode, sourceFile).replace(new RegExp(`${paramNode.name.getText()}\\??: `), "").replaceAll(/\s+/g, " "); for (const { initial, replacedWith } of replace) { result = result.replace(initial, replacedWith); } return result; } function expandType(decl, sourceFile, printer) { const props = decl.members.map((member) => printer.printNode(ts8.EmitHint.Unspecified, member, sourceFile)).join(" ").replaceAll(/\s+/g, " "); return `{${props}}`; } // packages/compiler-cli/src/ngtsc/docs/src/enum_extractor.js import ts9 from "typescript"; function extractEnum(declaration, typeChecker) { return { name: declaration.name.getText(), entryType: EntryType.Enum, members: extractEnumMembers(declaration, typeChecker), rawComment: extractRawJsDoc(declaration), description: extractJsDocDescription(declaration), jsdocTags: extractJsDocTags(declaration) }; } function extractEnumMembers(declaration, checker) { return declaration.members.map((member) => ({ name: member.name.getText(), type: extractResolvedTypeString(member, checker), value: getEnumMemberValue(member), memberType: MemberType.EnumItem, jsdocTags: extractJsDocTags(member), description: extractJsDocDescription(member), memberTags: [] })); } function getEnumMemberValue(memberNode) { const literal = memberNode.getChildren().find((n) => { return ts9.isNumericLiteral(n) || ts9.isStringLiteral(n) || ts9.isPrefixUnaryExpression(n) && n.operator === ts9.SyntaxKind.MinusToken && ts9.isNumericLiteral(n.operand); }); return literal?.getText() ?? ""; } // packages/compiler-cli/src/ngtsc/docs/src/initializer_api_function_extractor.js import ts10 from "typescript"; var initializerApiTag = "initializerApiFunction"; function isInitializerApiFunction(node, typeChecker) { if (ts10.isFunctionDeclaration(node) && node.name !== void 0 && node.body === void 0) { const implementation = findImplementationOfFunction(node, typeChecker); if (implementation !== void 0) { node = implementation; } } if (!ts10.isFunctionDeclaration(node) && !ts10.isVariableDeclaration(node)) { return false; } let tagContainer = ts10.isFunctionDeclaration(node) ? node : getContainerVariableStatement(node); if (tagContainer === null) { return false; } const tags = ts10.getJSDocTags(tagContainer); return tags.some((t) => t.tagName.text === initializerApiTag); } function extractInitializerApiFunction(node, typeChecker) { if (node.name === void 0 || !ts10.isIdentifier(node.name)) { throw new Error(`Initializer API: Expected literal variable name.`); } const container = ts10.isFunctionDeclaration(node) ? node : getContainerVariableStatement(node); if (container === null) { throw new Error("Initializer API: Could not find container AST node of variable."); } const name = node.name.text; const type = typeChecker.getTypeAtLocation(node); const callFunction = extractFunctionWithOverloads(name, type, typeChecker); const subFunctions = []; for (const property of type.getProperties()) { const subName = property.getName(); const subDecl = property.getDeclarations()?.[0]; if (subDecl === void 0 || !ts10.isPropertySignature(subDecl)) { throw new Error(`Initializer API: Could not resolve declaration of sub-property: ${name}.${subName}`); } const subType = typeChecker.getTypeAtLocation(subDecl); subFunctions.push(extractFunctionWithOverloads(subName, subType, typeChecker)); } let jsdocTags; let description; let rawComment; if (ts10.isFunctionDeclaration(node)) { const implementation = findImplementationOfFunction(node, typeChecker); if (implementation === void 0) { throw new Error(`Initializer API: Could not find implementation of function: ${name}`); } callFunction.implementation = { name, entryType: EntryType.Function, isNewType: false, description: extractJsDocDescription(implementation), generics: extractGenerics(implementation), jsdocTags: extractJsDocTags(implementation), params: extractAllParams(implementation.parameters, typeChecker), rawComment: extractRawJsDoc(implementation), returnType: typeChecker.typeToString(typeChecker.getReturnTypeOfSignature(typeChecker.getSignatureFromDeclaration(implementation))) }; jsdocTags = callFunction.implementation.jsdocTags; description = callFunction.implementation.description; rawComment = callFunction.implementation.description; } else { jsdocTags = extractJsDocTags(container); description = extractJsDocDescription(container); rawComment = extractRawJsDoc(container); } const metadataTag = jsdocTags.find((t) => t.name === initializerApiTag); if (metadataTag === void 0) { throw new Error(`Initializer API: Detected initializer API function does not have "@initializerApiFunction" tag: ${name}`); } let parsedMetadata = void 0; if (metadataTag.comment.trim() !== "") { try { parsedMetadata = JSON.parse(metadataTag.comment); } catch (e) { throw new Error(`Could not parse initializer API function metadata: ${e}`); } } return { entryType: EntryType.InitializerApiFunction, name, description, jsdocTags, rawComment, callFunction, subFunctions, __docsMetadata__: parsedMetadata }; } function getContainerVariableStatement(node) { if (!ts10.isVariableDeclarationList(node.parent)) { return null; } if (!ts10.isVariableStatement(node.parent.parent)) { return null; } return node.parent.parent; } function extractFunctionWithOverloads(name, type, typeChecker) { return { name, signatures: extractCallSignatures(name, typeChecker, type), // Implementation may be populated later. implementation: null }; } // packages/compiler-cli/src/ngtsc/docs/src/type_alias_extractor.js function extractTypeAlias(declaration) { return { name: declaration.name.getText(), type: declaration.type.getText(), entryType: EntryType.TypeAlias, generics: extractGenerics(declaration), rawComment: extractRawJsDoc(declaration), description: extractJsDocDescription(declaration), jsdocTags: extractJsDocTags(declaration) }; } // packages/compiler-cli/src/ngtsc/docs/src/import_extractor.js import ts11 from "typescript"; function getImportedSymbols(sourceFile) { const importSpecifiers = /* @__PURE__ */ new Map(); function visit(node) { if (ts11.isImportDeclaration(node)) { let moduleSpecifier = node.moduleSpecifier.getText(sourceFile).replace(/['"]/g, ""); if (moduleSpecifier.startsWith("@angular/")) { const namedBindings = node.importClause?.namedBindings; if (namedBindings && ts11.isNamedImports(namedBindings)) { namedBindings.elements.forEach((importSpecifier) => { const importName = importSpecifier.name.text; const importAlias = importSpecifier.propertyName ? importSpecifier.propertyName.text : void 0; importSpecifiers.set(importAlias ?? importName, moduleSpecifier); }); } } } ts11.forEachChild(node, visit); } visit(sourceFile); return importSpecifiers; } // packages/compiler-cli/src/ngtsc/docs/src/extractor.js var DocsExtractor = class { typeChecker; metadataReader; constructor(typeChecker, metadataReader) { this.typeChecker = typeChecker; this.metadataReader = metadataReader; } /** * Gets the set of all documentable entries from a source file, including * declarations that are re-exported from this file as an entry-point. * * @param sourceFile The file from which to extract documentable entries. */ extractAll(sourceFile, rootDir, privateModules) { const entries = []; const symbols = /* @__PURE__ */ new Map(); const exportedDeclarations = this.getExportedDeclarations(sourceFile); for (const [exportName, node] of exportedDeclarations) { if (isAngularPrivateName(exportName)) { continue; } const entry = this.extractDeclaration(node); if (entry && !isIgnoredDocEntry(entry)) { const realSourceFile = node.getSourceFile(); const importedSymbols = getImportedSymbols(realSourceFile); importedSymbols.forEach((moduleName, symbolName) => { if (symbolName.startsWith("\u0275") || privateModules.has(moduleName)) { return; } if (symbols.has(symbolName) && symbols.get(symbolName) !== moduleName) { throw new Error(`Ambigous symbol \`${symbolName}\` exported by both ${symbols.get(symbolName)} & ${moduleName}`); } symbols.set(symbolName, moduleName); }); entry.source = { filePath: getRelativeFilePath(realSourceFile, rootDir), // Start & End are off by 1 startLine: ts12.getLineAndCharacterOfPosition(realSourceFile, node.getStart()).line + 1, endLine: ts12.getLineAndCharacterOfPosition(realSourceFile, node.getEnd()).line + 1 }; entries.push({ ...entry, name: exportName }); } } return { entries, symbols }; } /** Extract the doc entry for a single declaration. */ extractDeclaration(node) { if (isNamedClassDeclaration(node)) { return extractClass(node, this.metadataReader, this.typeChecker); } if (isInitializerApiFunction(node, this.typeChecker)) { return extractInitializerApiFunction(node, this.typeChecker); } if (ts12.isInterfaceDeclaration(node) && !isIgnoredInterface(node)) { return extractInterface(node, this.typeChecker); } if (ts12.isFunctionDeclaration(node)) { const functionExtractor = new FunctionExtractor(node.name.getText(), node, this.typeChecker); return functionExtractor.extract(); } if (ts12.isVariableDeclaration(node) && !isSyntheticAngularConstant(node)) { return isDecoratorDeclaration(node) ? extractorDecorator(node, this.typeChecker) : extractConstant(node, this.typeChecker); } if (ts12.isTypeAliasDeclaration(node)) { return extractTypeAlias(node); } if (ts12.isEnumDeclaration(node)) { return extractEnum(node, this.typeChecker); } return null; } /** Gets the list of exported declarations for doc extraction. */ getExportedDeclarations(sourceFile) { const reflector = new TypeScriptReflectionHost(this.typeChecker, false, true); const exportedDeclarationMap = reflector.getExportsOfModule(sourceFile); let exportedDeclarations = Array.from(exportedDeclarationMap?.entries() ?? []).map(([exportName, declaration]) => [exportName, declaration.node]); return exportedDeclarations.sort(([a, declarationA], [b, declarationB]) => declarationA.pos - declarationB.pos); } }; function isIgnoredInterface(node) { return node.name.getText().endsWith("Decorator") || isDecoratorOptionsInterface(node); } function isIgnoredDocEntry(entry) { const isDocsPrivate = entry.jsdocTags.find((e) => e.name === "docsPrivate"); if (isDocsPrivate !== void 0 && isDocsPrivate.comment === "") { throw new Error(`Docs extraction: Entry "${entry.name}" is marked as "@docsPrivate" but without reasoning.`); } return isDocsPrivate !== void 0; } function getRelativeFilePath(sourceFile, rootDir) { const fullPath = sourceFile.fileName; const relativePath = fullPath.replace(rootDir, ""); return relativePath; } // packages/compiler-cli/src/ngtsc/program.js import { HtmlParser, MessageBundle } from "@angular/compiler"; import ts27 from "typescript"; // packages/compiler-cli/src/transformers/i18n.js import { Xliff, Xliff2, Xmb } from "@angular/compiler"; import * as path from "path"; function i18nGetExtension(formatName) { const format = formatName.toLowerCase(); switch (format) { case "xmb": return "xmb"; case "xlf": case "xlif": case "xliff": case "xlf2": case "xliff2": return "xlf"; } throw new Error(`Unsupported format "${formatName}"`); } function i18nExtract(formatName, outFile, host, options, bundle, pathResolve = path.resolve) { formatName = formatName || "xlf"; const ext = i18nGetExtension(formatName); const content = i18nSerialize(bundle, formatName, options); const dstFile = outFile || `messages.${ext}`; const dstPath = pathResolve(options.outDir || options.basePath, dstFile); host.writeFile(dstPath, content, false, void 0, []); return [dstPath]; } function i18nSerialize(bundle, formatName, options) { const format = formatName.toLowerCase(); let serializer; switch (format) { case "xmb": serializer = new Xmb(); break; case "xliff2": case "xlf2": serializer = new Xliff2(); break; case "xlf": case "xliff": default: serializer = new Xliff(); } return bundle.write(serializer, getPathNormalizer(options.basePath)); } function getPathNormalizer(basePath) { return (sourcePath) => { sourcePath = basePath ? path.relative(basePath, sourcePath) : sourcePath; return sourcePath.split(path.sep).join("/"); }; } // packages/compiler-cli/src/typescript_support.js import ts13 from "typescript"; // packages/compiler-cli/src/version_helpers.js function toNumbers(value) { const suffixIndex = value.lastIndexOf("-"); return value.slice(0, suffixIndex === -1 ? value.length : suffixIndex).split(".").map((segment) => { const parsed = parseInt(segment, 10); if (isNaN(parsed)) { throw Error(`Unable to parse version string ${value}.`); } return parsed; }); } function compareNumbers(a, b) { const max = Math.max(a.length, b.length); const min = Math.min(a.length, b.length); for (let i = 0; i < min; i++) { if (a[i] > b[i]) return 1; if (a[i] < b[i]) return -1; } if (min !== max) { const longestArray = a.length === max ? a : b; const comparisonResult = a.length === max ? 1 : -1; for (let i = min; i < max; i++) { if (longestArray[i] > 0) { return comparisonResult; } } } return 0; } function compareVersions(v1, v2) { return compareNumbers(toNumbers(v1), toNumbers(v2)); } // packages/compiler-cli/src/typescript_support.js var MIN_TS_VERSION = "5.8.0"; var MAX_TS_VERSION = "5.9.0"; var tsVersion = ts13.version; function checkVersion(version, minVersion, maxVersion) { if (compareVersions(version, minVersion) < 0 || compareVersions(version, maxVersion) >= 0) { throw new Error(`The Angular Compiler requires TypeScript >=${minVersion} and <${maxVersion} but ${version} was found instead.`); } }