From 815818a1764f102271cd9ffe468d28657be38732 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Oct 2026 11:34:11 -0700 Subject: [PATCH 1/6] script + accepted.txt --- tools/scripts/gen/apiDiff.mts | 295 +++++++ tsc/testdata/apiAccepted.txt | 9 + tsc/testdata/apiDiff.txt | 1367 +++++++++++++++++++++++++++++++++ 3 files changed, 1671 insertions(+) create mode 100644 tools/scripts/gen/apiDiff.mts create mode 100644 tsc/testdata/apiAccepted.txt create mode 100644 tsc/testdata/apiDiff.txt diff --git a/tools/scripts/gen/apiDiff.mts b/tools/scripts/gen/apiDiff.mts new file mode 100644 index 0000000000000..df2ed72d35fa4 --- /dev/null +++ b/tools/scripts/gen/apiDiff.mts @@ -0,0 +1,295 @@ +import fs from "node:fs"; +import path from "node:path"; +import ts from "typescript"; +import { repoRoot } from "./utils.mts"; + +const oldApiPath = path.join(repoRoot, "node_modules", "typescript", "lib", "typescript.d.ts"); +const newApiPackageDirectory = path.join(repoRoot, "packages", "typescript"); +const newApiEntryPoints = [ + "src/api/async/api.ts", + "src/api/fs.ts", + "src/api/proto.ts", + "src/ast/index.ts", + "src/ast/is.ts", + "src/ast/factory.generated.ts", + "src/ast/utils.ts", + "src/ast/scanner.ts", + "src/ast/visitor.ts", + "src/ast/clone.ts", +].map(file => path.join(newApiPackageDirectory, file)); +const outputPath = path.join(repoRoot, "tsc", "testdata", "apiDiff.txt"); +const typeMappings = new Map([ + ["TypeChecker", "Checker"], + ["BuilderProgram", "Program"], + ["Program", "Program"], + ["SolutionBuilder", "BuildOrchestrator"], + ["Project", "Project"], + ["LanguageService", "Project"], + ["Scanner", "Scanner"], + ["Printer", "Printer"], + ["Signature", "Signature"], + ["SourceFile", "SourceFile"], + ["Symbol", "Symbol"], + ["Type", "Type"], + ["Node", "Node"], + ["ts", "ts"], +]); + +const typescriptVersion = JSON.parse( + fs.readFileSync(path.join(repoRoot, "node_modules", "typescript", "package.json"), "utf8"), +).version as string; +const oldApiSourceFiles = [createSourceFile(oldApiPath)]; +const newApiProgram = createNewApiProgram(); +const newApiChecker = newApiProgram.getTypeChecker(); +const newApiExports = getEntryPointExports(newApiProgram, newApiChecker, newApiEntryPoints); + +const oldApiTypes = getTypesWithMethods(oldApiSourceFiles, visitOld); +oldApiTypes.set("ts", getNamespaceFunctions(oldApiSourceFiles, "ts")); + +const newApiTypes = getExportedTypesWithMethods(newApiExports); +newApiTypes.set("ts", [getExportedTopLevelFunctions(newApiExports, newApiChecker), new Set()]); + +const acceptedDiffs = getAcceptedDiffs(); + +const report: string[] = [ + "# This report is generated by tools/scripts/gen/apidiff.mts.", + `# Old API: TypeScript ${typescriptVersion} (node_modules/typescript/lib/typescript.d.ts)`, + "# New API: public package entry points", +]; + +const comparisons = [...typeMappings].map(([oldType, newType]) => { + const oldMethods = oldApiTypes.get(oldType)!; + const newMethods = newApiTypes.get(newType)!; + const acceptedChanges = acceptedDiffs.get(oldType) ?? new Map(); + const present: string[] = []; + const missing: string[] = []; + for (const method of oldMethods) { + if (newMethods[0].has(method)) { + present.push(method); + newMethods[0].delete(method); + newMethods[1].add(method); + } + else if (newMethods[1].has(method)) { + present.push(method); + } + else if (acceptedChanges.has(method)) { + present.push(method); + const [newType, newMethodName] = acceptedChanges.get(method)!.split("."); + const actualNewType = newApiTypes.get(newType); + if (actualNewType) { + actualNewType[0].delete(newMethodName); + actualNewType[1].add(method); + } + } + else { + missing.push(method); + } + } + return { + oldType, + newType, + present: present.sort(), + missing: missing.sort(), + }; +}); + +report.push( + `Types not compared:`, +); +for (const [type, _] of oldApiTypes) { + typeMappings.has(type) || report.push(`- ${type}`); +} +report.push( + "", +); + +for (const comparison of comparisons) { + const { oldType, newType, present, missing } = comparison; + report.push( + "", + `# ${oldType} (old) methods compared to ${newType} (new).`, + `## (${present.length}) ${oldType} methods matched in async ${newType} ##`, + "", + `## ${oldType} methods missing from async ${newType} (${missing.length}) ##`, + ...missing, + "", + ); +} + +for (const [newType, newMethods] of newApiTypes) { + report.push( + `## New ${newType} methods in async API (${newMethods[0].size}) ##`, + ...newMethods[0], + "", + ); +} + +fs.writeFileSync(outputPath, report.join("\n")); + +function createSourceFile(file: string): ts.SourceFile { + return ts.createSourceFile( + file, + fs.readFileSync(file, "utf8"), + ts.ScriptTarget.Latest, + true, + ); +} + +function createNewApiProgram(): ts.Program { + const configPath = path.join(newApiPackageDirectory, "tsconfig.json"); + const configFile = ts.readConfigFile(configPath, ts.sys.readFile); + if (configFile.error) { + throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n")); + } + const config = ts.parseJsonConfigFileContent(configFile.config, ts.sys, newApiPackageDirectory, { noEmit: true }, configPath); + if (config.errors.length > 0) { + throw new Error(config.errors.map(error => ts.flattenDiagnosticMessageText(error.messageText, "\n")).join("\n")); + } + return ts.createProgram({ + rootNames: config.fileNames, + options: config.options, + projectReferences: config.projectReferences, + }); +} + +type EntryPointExports = ReadonlyMap>; + +function getEntryPointExports(program: ts.Program, checker: ts.TypeChecker, entryPoints: readonly string[]): EntryPointExports { + const exports = new Map>(); + for (const entryPoint of entryPoints) { + const sourceFile = program.getSourceFile(entryPoint); + if (!sourceFile) throw new Error(`Could not find API entry point ${entryPoint}`); + const moduleSymbol = checker.getSymbolAtLocation(sourceFile); + if (!moduleSymbol) throw new Error(`Could not resolve API entry point ${entryPoint}`); + for (const exportedSymbol of checker.getExportsOfModule(moduleSymbol)) { + const symbols = exports.get(exportedSymbol.name) ?? new Set(); + symbols.add(resolveAlias(exportedSymbol, checker)); + exports.set(exportedSymbol.name, symbols); + } + } + return exports; +} + +function resolveAlias(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol { + return symbol.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol; +} + +function getTypesWithMethods(sourceFiles: readonly ts.SourceFile[], visitNode: (node: ts.Node, types: Map) => void): Map { + const types = new Map(); + for (const sourceFile of sourceFiles) { + visit(sourceFile); + } + return types; + + function visit(node: ts.Node): void { + visitNode(node, types); + ts.forEachChild(node, visit); + } +} + +function getAcceptedDiffs(): Map> { + const diffs = new Map>(); + const contents = fs.readFileSync(path.join(repoRoot, "tsc", "testdata", "apiAccepted.txt"), "utf-8").split("\n"); + contents.slice(2).forEach(line => { + const [oldMethod, newMethod, _] = line.split("|"); + const [oldType, oldMethodName] = oldMethod.split("."); + if (!diffs.has(oldType)) diffs.set(oldType, new Map()); + diffs.get(oldType)!.set(oldMethodName, newMethod); + }); + return diffs; +} + +function visitOld(node: ts.Node, types: Map>): void { + if ((ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.name) { + const methods = types.get(node.name.text) ?? new Set(); + for (const member of node.members) { + if ( + (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) + && !hasModifier(member, ts.SyntaxKind.PrivateKeyword) + && !hasModifier(member, ts.SyntaxKind.ProtectedKeyword) + ) { + const name = getPropertyName(member.name); + if (name !== undefined) methods.add(name); + } + } + if (methods.size > 0) types.set(node.name.text, methods); + } +} + +function getExportedTypesWithMethods(exports: EntryPointExports): Map, seen: Set]> { + const types = new Map, seen: Set]>(); + for (const [exportName, symbols] of exports) { + const methods = new Set(); + for (const symbol of symbols) { + for (const declaration of symbol.declarations ?? []) { + if (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) { + addPublicMethods(declaration.members, methods); + } + } + } + if (methods.size > 0) types.set(exportName, [methods, new Set()]); + } + return types; +} + +function addPublicMethods(members: ts.NodeArray, methods: Set): void { + for (const member of members) { + if ( + (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) + && !hasModifier(member, ts.SyntaxKind.PrivateKeyword) + && !hasModifier(member, ts.SyntaxKind.ProtectedKeyword) + ) { + const name = getPropertyName(member.name); + if (name !== undefined) methods.add(name); + } + } +} + +function getNamespaceFunctions(sourceFiles: readonly ts.SourceFile[], namespace: string): Set { + const functions = new Set(); + for (const sourceFile of sourceFiles) { + for (const statement of sourceFile.statements) { + if ( + ts.isModuleDeclaration(statement) + && statement.name.text === namespace + && statement.body + && ts.isModuleBlock(statement.body) + ) { + for (const member of statement.body.statements) { + if (ts.isFunctionDeclaration(member) && member.name) { + functions.add(member.name.text); + } + } + } + } + } + return functions; +} + +function getExportedTopLevelFunctions(exports: EntryPointExports, checker: ts.TypeChecker): Set { + const functions = new Set(); + for (const [exportName, symbols] of exports) { + for (const symbol of symbols) { + const declaration = symbol.valueDeclaration; + if ( + declaration + && checker.getTypeOfSymbolAtLocation(symbol, declaration).getCallSignatures().length > 0 + ) { + functions.add(exportName); + break; + } + } + } + return functions; +} + +function hasModifier(node: ts.Node, kind: ts.SyntaxKind): boolean { + return ts.canHaveModifiers(node) && ts.getModifiers(node)?.some(modifier => modifier.kind === kind) === true; +} + +function getPropertyName(name: ts.PropertyName): string | undefined { + if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) { + return name.text; + } + return undefined; +} diff --git a/tsc/testdata/apiAccepted.txt b/tsc/testdata/apiAccepted.txt new file mode 100644 index 0000000000000..7f27b957d80d5 --- /dev/null +++ b/tsc/testdata/apiAccepted.txt @@ -0,0 +1,9 @@ +originalType.MethodName|newType.MethodName|reason (will be discarded in parsing) +If the original + +TypeChecker.tryGetMemberInModuleExports|Checker.getMemberInModuleExports|rename +ts.parseCommandLine|API.parseCommandLine| +ts.parseJsonConfigFileContent|API.parseJsonConfigFileContent| +ts.parseConfigFileTextToJson|API.readConfigFile|the same minus error handling +ts.readConfigFile|API.readConfigFile| +ts.parseJsonSourceFileConfigFileContent|API.parseConfigFile| diff --git a/tsc/testdata/apiDiff.txt b/tsc/testdata/apiDiff.txt new file mode 100644 index 0000000000000..54169e00508be --- /dev/null +++ b/tsc/testdata/apiDiff.txt @@ -0,0 +1,1367 @@ +# This report is generated by tools/scripts/gen/apidiff.mts. +# Old API: TypeScript 6.0.3 (node_modules/typescript/lib/typescript.d.ts) +# New API: public package entry points +Types not compared: +- Log +- TypingsInstaller +- InstallTypingHost +- ServerHost +- ITypingsInstaller +- Logger +- NormalizedPathMap +- ScriptInfo +- PluginModule +- InferredProject +- AutoImportProviderProject +- ConfiguredProject +- ExternalProject +- ProjectService +- ServerCancellationToken +- Session +- TypingResolutionHost +- SourceFileLike +- ScriptReferenceHost +- ParseConfigHost +- CancellationToken +- CustomTransformer +- ModuleResolutionHost +- MinimalResolutionCacheHost +- CompilerHost +- SourceMapSource +- NodeFactory +- CoreTransformationContext +- TransformationContext +- TransformationResult +- PrintHandlers +- GetEffectiveTypeRootsHost +- System +- FileWatcher +- ParseConfigFileHost +- ModeAwareCache +- PerDirectoryResolutionCache +- NonRelativeNameResolutionCache +- PerNonRelativeNameCache +- ModuleResolutionCache +- NonRelativeModuleNameResolutionCache +- PackageJsonInfoCache +- FormatDiagnosticsHost +- SemanticDiagnosticsBuilderProgram +- EmitAndSemanticDiagnosticsBuilderProgram +- ReadBuildProgramHost +- WatchHost +- ProgramHost +- WatchCompilerHost +- WatchCompilerHostOfConfigFile +- Watch +- WatchOfFilesAndCompilerOptions +- SolutionBuilderHostBase +- InvalidatedProjectBase +- UpdateOutputFileStampsProject +- BuildInvalidedProject +- IScriptSnapshot +- HostCancellationToken +- IncompleteCompletionsCache +- LanguageServiceHost +- Classifier +- DocumentRegistry + + +# TypeChecker (old) methods compared to Checker (new). +## (60) TypeChecker methods matched in async Checker ## + +## TypeChecker methods missing from async Checker (29) ## +getAmbientModules +getAugmentedPropertiesOfType +getBigIntLiteralType +getFalseType +getJsxIntrinsicTagNamesAt +getNullableType +getNumberLiteralType +getPrivateIdentifierPropertyOfType +getPropertySymbolOfDestructuringAssignment +getRootSymbols +getStringLiteralType +getSymbolOfExpando +getSymbolsOfParameterPropertyDeclaration +getTrueType +getTypeArgumentsForResolvedSignature +getTypeOfAssignmentPattern +indexInfoToIndexSignatureDeclaration +isImplementationOfOverload +isOptionalParameter +isValidPropertyAccess +runWithCancellationToken +signatureToString +symbolToEntityName +symbolToExpression +symbolToParameterDeclaration +symbolToString +symbolToTypeParameterDeclarations +typeParameterToDeclaration +typePredicateToString + + +# BuilderProgram (old) methods compared to Program (new). +## (9) BuilderProgram methods matched in async Program ## + +## BuilderProgram methods missing from async Program (4) ## +getAllDependencies +getOptionsDiagnostics +getProgram +getSourceFiles + + +# Program (old) methods compared to Program (new). +## (11) Program methods matched in async Program ## + +## Program methods missing from async Program (12) ## +getIdentifierCount +getInstantiationCount +getNodeCount +getOptionsDiagnostics +getProjectReferences +getRelationCacheSizes +getResolvedProjectReferences +getRootFileNames +getSourceFiles +getSymbolCount +getTypeChecker +getTypeCount + + +# SolutionBuilder (old) methods compared to BuildOrchestrator (new). +## (4) SolutionBuilder methods matched in async BuildOrchestrator ## + +## SolutionBuilder methods missing from async BuildOrchestrator (1) ## +getNextInvalidatedProject + + +# Project (old) methods compared to Project (new). +## (0) Project methods matched in async Project ## + +## Project methods missing from async Project (61) ## +addMissingFileRoot +addRoot +close +containsFile +containsScriptInfo +directoryExists +disableLanguageService +emitFile +enableLanguageService +error +fileExists +filesToString +getAllProjectErrors +getCancellationToken +getCompilationSettings +getCompileOnSaveAffectedFileList +getCompilerOptions +getCurrentDirectory +getDefaultLibFileName +getDirectories +getExcludedFiles +getExternalFiles +getFileNames +getGlobalProjectErrors +getLanguageService +getNewLine +getProjectName +getProjectReferences +getProjectVersion +getRootFiles +getRootScriptInfos +getScriptFileNames +getScriptInfo +getScriptInfoForNormalizedPath +getScriptInfos +getScriptKind +getScriptSnapshot +getScriptVersion +getSourceFile +getTypeAcquisition +hasConfigFile +hasRoots +installPackage +isClosed +isJsOnlyProject +isKnownTypesPackageName +isNonTsProject +isRoot +log +readDirectory +readFile +refreshDiagnostics +registerFileUpdate +removeFile +resolveModule +setCompilerOptions +setProjectErrors +setTypeAcquisition +updateGraph +useCaseSensitiveFileNames +writeFile + + +# LanguageService (old) methods compared to Project (new). +## (1) LanguageService methods matched in async Project ## + +## LanguageService methods missing from async Project (64) ## +applyCodeActionCommand +cleanupSemanticCache +commentSelection +findReferences +findRenameLocations +getApplicableRefactors +getBraceMatchingAtPosition +getBreakpointStatementAtPosition +getCodeFixesAtPosition +getCombinedCodeFix +getCompilerOptionsDiagnostics +getCompletionEntryDetails +getCompletionEntrySymbol +getCompletionsAtPosition +getDefinitionAndBoundSpan +getDefinitionAtPosition +getDocCommentTemplateAtPosition +getDocumentHighlights +getEditsForFileRename +getEditsForRefactor +getEmitOutput +getEncodedSemanticClassifications +getEncodedSyntacticClassifications +getFileReferences +getFormattingEditsAfterKeystroke +getFormattingEditsForDocument +getFormattingEditsForRange +getImplementationAtPosition +getIndentationAtPosition +getJsxClosingTagAtPosition +getLinkedEditingRangeAtPosition +getMoveToRefactoringFileSuggestions +getNameOrDottedNameSpan +getNavigateToItems +getNavigationBarItems +getNavigationTree +getOutliningSpans +getPasteEdits +getProgram +getQuickInfoAtPosition +getReferencesAtPosition +getRenameInfo +getSemanticClassifications +getSemanticDiagnostics +getSignatureHelpItems +getSmartSelectionRange +getSpanOfEnclosingComment +getSuggestionDiagnostics +getSupportedCodeFixes +getSyntacticClassifications +getSyntacticDiagnostics +getTodoComments +getTypeDefinitionAtPosition +isValidBraceCompletionAtPosition +organizeImports +prepareCallHierarchy +preparePasteEditsForFile +provideCallHierarchyIncomingCalls +provideCallHierarchyOutgoingCalls +provideInlayHints +toLineColumnOffset +toggleLineComment +toggleMultilineComment +uncommentSelection + + +# Scanner (old) methods compared to Scanner (new). +## (35) Scanner methods matched in async Scanner ## + +## Scanner methods missing from async Scanner (8) ## +getStartPos +getTextPos +getTokenPos +setJSDocParsingMode +setOnError +setScriptKind +setScriptTarget +setTextPos + + +# Printer (old) methods compared to Printer (new). +## (2) Printer methods matched in async Printer ## + +## Printer methods missing from async Printer (2) ## +printBundle +printList + + +# Signature (old) methods compared to Signature (new). +## (4) Signature methods matched in async Signature ## + +## Signature methods missing from async Signature (3) ## +getDeclaration +getDocumentationComment +getJsDocTags + + +# SourceFile (old) methods compared to SourceFile (new). +## (3) SourceFile methods matched in async SourceFile ## + +## SourceFile methods missing from async SourceFile (2) ## +getLineEndOfPosition +update + + +# Symbol (old) methods compared to Symbol (new). +## (2) Symbol methods matched in async Symbol ## + +## Symbol methods missing from async Symbol (4) ## +getDeclarations +getEscapedName +getFlags +getName + + +# Type (old) methods compared to Type (new). +## (13) Type methods matched in async Type ## + +## Type methods missing from async Type (10) ## +getConstraint +getDefault +getFlags +isClass +isIntersection +isLiteral +isNumberLiteral +isStringLiteral +isUnion +isUnionOrIntersection + + +# Node (old) methods compared to Node (new). +## (15) Node methods matched in async Node ## + +## Node methods missing from async Node (0) ## + + +# ts (old) methods compared to ts (new). +## (275) ts methods matched in async ts ## + +## ts methods missing from async ts (213) ## +addEmitHelper +addEmitHelpers +addSyntheticLeadingComment +addSyntheticTrailingComment +bundlerModuleNameResolver +canHaveDecorators +canHaveModifiers +classicNameResolver +collapseTextChangeRangesAcrossMultipleVersions +convertCompilerOptionsFromJson +convertToObject +convertTypeAcquisitionFromJson +createAbstractBuilder +createBuilderStatusReporter +createClassifier +createCompilerHost +createDocumentRegistry +createEmitAndSemanticDiagnosticsBuilderProgram +createIncrementalCompilerHost +createIncrementalProgram +createLanguageService +createLanguageServiceSourceFile +createModuleResolutionCache +createPrinter +createProgram +createSemanticDiagnosticsBuilderProgram +createSolutionBuilder +createSolutionBuilderHost +createSolutionBuilderWithWatch +createSolutionBuilderWithWatchHost +createSourceMapSource +createTextChangeRange +createTextSpan +createTextSpanFromBounds +createTypeReferenceDirectiveResolutionCache +createWatchCompilerHost +createWatchProgram +decodedTextSpanIntersectsWith +displayPartsToString +disposeEmitNodes +findAncestor +findConfigFile +flattenDiagnosticMessageText +forEachChild +formatDiagnostic +getAutomaticTypeDirectiveNames +getCombinedNodeFlags +getCommentRange +getConfigFileParsingDiagnostics +getConstantValue +getDecorators +getDefaultCompilerOptions +getDefaultFormatCodeSettings +getDefaultLibFileName +getDefaultLibFilePath +getEffectiveConstraintOfTypeParameter +getEffectiveTypeParameterDeclarations +getEffectiveTypeRoots +getEmitHelpers +getImpliedNodeFormatForFile +getJSDocAugmentsTag +getJSDocClassTag +getJSDocDeprecatedTag +getJSDocEnumTag +getJSDocImplementsTags +getJSDocOverrideTagNoCache +getJSDocParameterTags +getJSDocPrivateTag +getJSDocProtectedTag +getJSDocPublicTag +getJSDocReadonlyTag +getJSDocReturnTag +getJSDocReturnType +getJSDocSatisfiesTag +getJSDocTemplateTag +getJSDocThisTag +getJSDocType +getJSDocTypeParameterTags +getJSDocTypeTag +getLineAndCharacterOfPosition +getModeForFileReference +getModeForResolutionAtIndex +getModeForUsageLocation +getModifiers +getNameOfJSDocTypedef +getOriginalNode +getOutputFileNames +getParseTreeNode +getParsedCommandLineOfConfigFile +getPositionOfLineAndCharacter +getPreEmitDiagnostics +getSourceMapRange +getSupportedCodeFixes +getSyntheticLeadingComments +getSyntheticTrailingComments +getTokenSourceMapRange +getTsBuildInfoEmitOutputFilePath +getTypeParameterOwner +hasJSDocParameterTags +hasOnlyExpressionInitializer +hasRestParameter +idText +identifierToKeywordKind +isAccessor +isAssertClause +isAssertEntry +isAutoAccessorPropertyDeclaration +isBuildCommand +isBundle +isCallChain +isCaseOrDefaultClause +isClassElement +isClassLike +isClassOrTypeElement +isCommaListExpression +isConstTypeReference +isDeclarationStatement +isElementAccessChain +isEmptyBindingElement +isEmptyBindingPattern +isExternalModuleNameRelative +isFunctionLike +isFunctionOrConstructorTypeNode +isGetAccessor +isImportOrExportSpecifier +isImportTypeAssertionContainer +isInternalDeclaration +isIterationStatement +isJSDocAuthorTag +isJSDocClassTag +isJSDocCommentContainingNode +isJSDocEnumTag +isJSDocFunctionType +isJSDocLinkLike +isJSDocMemberName +isJSDocNamepathType +isJSDocPropertyLikeTag +isJSDocUnknownType +isJsxCallLike +isMethodSignature +isNonNullChain +isNullishCoalesce +isObjectLiteralElement +isOptionalChain +isParameter +isParameterPropertyDeclaration +isParseTreeNode +isPartOfTypeNode +isPartOfTypeOnlyImportOrExportDeclaration +isPropertyAccessChain +isPropertyAccessOrQualifiedName +isPropertySignature +isRestParameter +isSetAccessor +isStringLiteralLike +isStringLiteralOrJsxExpression +isStringTextContainingNode +isTypeAssertionExpression +isTypeElement +isTypeOnlyExportDeclaration +isTypeOnlyImportDeclaration +isTypeOnlyImportOrExportDeclaration +moveEmitHelpers +moveSyntheticComments +nodeModuleNameResolver +parseBuildCommand +parseIsolatedEntityName +parseJsonText +preProcessFile +readBuilderProgram +readJsonConfigFile +removeEmitHelper +resolveModuleName +resolveModuleNameFromCache +resolveProjectReferencePath +resolveTripleslashReference +resolveTypeReferenceDirective +setCommentRange +setConstantValue +setEmitFlags +setOriginalNode +setSourceMapRange +setSyntheticLeadingComments +setSyntheticTrailingComments +setTextRange +setTokenSourceMapRange +sortAndDeduplicateDiagnostics +symbolName +textChangeRangeIsUnchanged +textChangeRangeNewSpan +textSpanContainsPosition +textSpanContainsTextSpan +textSpanEnd +textSpanIntersection +textSpanIntersectsWith +textSpanIntersectsWithPosition +textSpanIntersectsWithTextSpan +textSpanIsEmpty +textSpanOverlap +textSpanOverlapsWith +toEditorSettings +transform +transpile +transpileDeclaration +transpileModule +updateLanguageServiceSourceFile +validateLocaleAndSetLanguage +visitCommaListElements +visitFunctionBody +visitIterationBody +visitLexicalEnvironment +visitParameterList +walkUpBindingElementsAndPatterns + +## New ConditionalType methods in async API (4) ## +getCheckType +getExtendsType +getTrueType +getFalseType + +## New FormatDiagnosticsHost methods in async API (3) ## +getCurrentDirectory +getCanonicalFileName +getNewLine + +## New FreshableType methods in async API (2) ## +getFreshType +getRegularType + +## New IndexedAccessType methods in async API (2) ## +getObjectType +getIndexType + +## New IndexType methods in async API (1) ## +getTarget + +## New InterfaceType methods in async API (4) ## +getTypeParameters +getOuterTypeParameters +getLocalTypeParameters +getThisType + +## New MappedType methods in async API (4) ## +getTypeParameter +getConstraintType +getNameType +getTemplateType + +## New StringMappingType methods in async API (1) ## +getTarget + +## New SubstitutionType methods in async API (2) ## +getBaseType +getConstraint + +## New TemplateLiteralType methods in async API (1) ## +getTypes + +## New TupleType methods in async API (1) ## +getTarget + +## New TupleTypeReference methods in async API (1) ## +getTarget + +## New Type methods in async API (24) ## +getApparentType +getReducedType +getIndexInfos +getAliasTypeArguments +getAliasSymbol +isUnionType +isIntersectionType +isObjectType +isIntrinsicType +isErrorType +isLiteralType +isStringLiteralType +isNumberLiteralType +isBigIntLiteralType +isBooleanLiteralType +isTypeReference +isTupleType +isTupleTypeTarget +isIndexedAccessType +isConditionalType +isSubstitutionType +isTemplateLiteralType +isStringMappingType +isMappedType + +## New TypeParameter methods in async API (2) ## +getConstraint +getDefault + +## New TypeReference methods in async API (1) ## +getTarget + +## New UnionOrIntersectionType methods in async API (1) ## +getTypes + +## New API methods in async API (23) ## +getSymbol +fromLSPConnection +batchContext +getCurrentDirectory +getCanonicalFileName +getNewLine +createBuildOrchestrator +createSourceFile +createSourceFileFromFile +retainSourceFile +transpileModule +transpileModuleFromFile +transpileDeclaration +transpileDeclarationFromFile +createSnapshot +getCurrentLanguageServerSnapshot +close +createModuleResolver +clearSourceFileCache +runWithTemporaryFileUpdate +getTimingInfo +resetTimingInfo +createProgram + +## New RetainedSourceFile methods in async API (1) ## +dispose + +## New DebugHandlers methods in async API (3) ## +startCPUProfile +stopCPUProfile +saveHeapProfile + +## New Snapshot methods in async API (8) ## +getProjects +getConfiguredProject +getProject +getProgram +update +getDefaultProjectForFile +dispose +isDisposed + +## New ModuleResolver methods in async API (3) ## +resolveModuleName +dispose +ensureNotDisposed + +## New Project methods in async API (0) ## + +## New LanguageService methods in async API (6) ## +getImportAdderEdits +getImportEditsForSymbols +getReferencedSymbolsForNode +getSignatureUsage +getCompletionsAtPosition +formatNodeForInsertion + +## New Program methods in async API (21) ## +getCanonicalFileName +getNewLine +setOwnedSnapshot +dispose +getSourceFileByPath +getResolvedModule +getResolvedModuleFromModuleSpecifier +getResolvedTypeReferenceDirective +getResolvedTypeReferenceDirectiveFromTypeReferenceDirective +getSourceFileNames +getSourceFileMetadata +getSourceFileMetadataByPath +getConfigFileNames +getConfigSourceFile +getBindDiagnostics +getSuggestionDiagnostics +getProgramDiagnostics +emitToString +getJavaScriptEmit +getDeclarationEmit +getProject + +## New BuildOrchestrator methods in async API (2) ## +dispose +isDisposed + +## New Checker methods in async API (23) ## +dispose +getSymbolOfNode +getSymbolOfDeclaration +getParentOfSymbol +getSymbolAtPosition +getSymbolOfSourceFile +getNonMissingTypeOfSymbol +getReferencesToSymbolInFile +getTypeAtPosition +getResolvedSymbol +getContextualTypeForArgumentAtIndex +getParameterType +isContextSensitive +isTupleTypeTarget +isReadonlySymbol +getRestTypeOfSignature +getReducedType +getTypeOfPropertyOfType +getConstraintOfTypeParameter +getTargetSymbol +isUnknownSignature +getJsDocTagsOfSymbol +getDocumentationCommentOfSymbol + +## New Printer methods in async API (0) ## + +## New NodeHandle methods in async API (1) ## +resolve + +## New Symbol methods in async API (4) ## +getParent +getMembers +getExports +getExportSymbol + +## New Signature methods in async API (2) ## +getThisParameter +getTarget + +## New Node methods in async API (1) ## +childrenIter + +## New SourceFile methods in async API (0) ## + +## New Scanner methods in async API (10) ## +hasPrecedingJSDocComment +hasPrecedingJSDocLeadingAsterisks +hasPrecedingJSDocWithDeprecatedTag +hasPrecedingJSDocWithSeeOrLink +getNumericLiteralFlags +getCommentDirectives +getTokenFlags +scanJSDocCommentTextToken +clearCommentDirectives +setSkipJsDocLeadingAsterisks + +## New SpanMap methods in async API (9) ## +isExact +isSingleSegment +isNone +virtualToOriginalSpan +virtualToOriginalSpanForFeature +virtualToOriginalPosition +virtualToOriginalPositionForFeature +originalToVirtualPositions +originalToVirtualSpans + +## New NodeObject methods in async API (16) ## +forEachChild +childrenIter +getSourceFile +getStart +getFullStart +getEnd +getWidth +getFullWidth +getLeadingTriviaWidth +getFullText +getText +getChildCount +getChildAt +getChildren +getFirstToken +getLastToken + +## New ts methods in async API (545) ## +isRemoteNode +getSymbol +isUnionType +isIntersectionType +isObjectType +isClassOrInterfaceType +isIntrinsicType +isErrorType +isLiteralType +isStringLiteralType +isNumberLiteralType +isBigIntLiteralType +isBooleanLiteralType +isTypeReference +isTupleType +isTupleTypeTarget +isIndexType +isIndexedAccessType +isConditionalType +isSubstitutionType +isTemplateLiteralType +isStringMappingType +isTypeParameter +documentURIToFileName +fileNameToDocumentURI +createFileSystem +createFileSystemWithLib +createFileSystemLayer +validateSymbolOwner +validateSymbolResponse +resolveFileName +resolveDocumentURI +getTokenAtPosition +getTouchingPropertyName +getTouchingToken +findNextToken +findPrecedingToken +getTokenPosOfNode +getChildren +getFirstToken +getLastToken +getSynthesizedDeepClone +getSynthesizedDeepClones +isValidTypeOnlyAliasUseSite +isBlockOrExpression +isUnaryExpression +isOuterExpression +skipOuterExpressions +isBindingPattern +isIdentifierOrJSDocNamespaceDeclaration +isJSDocTypeExpressionOrJSDocTypeLiteral +isParameterDeclaration +isNotEmittedTypeElement +isMethodSignatureDeclaration +isPropertySignatureDeclaration +isKeywordExpression +isTypeAssertion +isKeywordTypeNode +isSyntaxList +isJSDocText +isSyntheticReferenceExpression +isHeritageClauseElement +isAccessExpression +isDeclarationName +isJSDocFullName +isJsxAttributeName +isJsxAttributeValue +isClassLikeDeclaration +isAccessorDeclaration +isLiteralLikeNode +isUnionOrIntersectionTypeNode +isTemplateLiteralLikeNode +isTemplateMiddleOrTail +isTypePredicateParameterName +isJSDocComment +isSignatureDeclaration +isStringLiteralLikeNode +isNumericOrStringLikeLiteral +isObjectLiteralLikeNode +isObjectTypeDeclaration +isNamedImportsOrExports +isFunctionLikeDeclaration +isVariableOrParameterDeclaration +isVariableOrPropertyDeclaration +isImportClauseOrBindingPattern +isAnyImportSyntax +isBooleanLiteral +isDestructuringAssignment +isLiteralToken +isPropertyNameLiteral +isPseudoLiteralToken +isArrayDestructuringAssignment +isObjectDestructuringAssignment +isFunctionBody +isTriviaKind +isPseudoLiteralKind +isModifierKind +isKeywordTypeKind +isKeywordExpressionKind +isJsxTokenKind +isImportPhaseModifierKind +isPostfixUnaryOperator +isPrefixUnaryOperator +isAssignmentOperator +isBinaryOperator +isExponentiationOperator +isMultiplicativeOperator +isMultiplicativeOperatorOrHigher +isAdditiveOperator +isAdditiveOperatorOrHigher +isShiftOperator +isShiftOperatorOrHigher +isRelationalOperator +isRelationalOperatorOrHigher +isEqualityOperator +isEqualityOperatorOrHigher +isBitwiseOperator +isBitwiseOperatorOrHigher +isLogicalOperator +isLogicalOperatorOrHigher +isCompoundAssignmentOperator +isAssignmentOperatorOrHigher +isLogicalOrCoalescingAssignmentOperator +isLiteralKind +isPunctuationKind +isKeywordKind +isJSDocNodeKind +isEndOfFile +isDotToken +isEqualsToken +isAssertKeyword +isCaseKeyword +isAbstractKeyword +isAccessorKeyword +isAsyncKeyword +isConstKeyword +isDeclareKeyword +isDefaultKeyword +isExportKeyword +isInKeyword +isPrivateKeyword +isProtectedKeyword +isPublicKeyword +isReadonlyKeyword +isOutKeyword +isOverrideKeyword +isStaticKeyword +isAssignmentOperatorToken +isNullLiteral +isTrueLiteral +isFalseLiteral +isThisExpression +isSuperExpression +isImportExpression +tokenIsIdentifierOrKeyword +tokenIsIdentifierOrKeywordOrGreaterThan +isUnicodeIdentifierStart +stringToToken +characterCodeToRegularExpressionFlag +computeLineStarts +skipTrivia +isIdentifierText +utf16EncodeAsString +formatSyntaxKind +tryGetAmbientModuleNameFromSymbolName +tryCast +cast +hasExpression +hasInitializer +hasObjectAssignmentInitializer +cloneSourceFileData +visitNodesArray +forEachChildOfJSDocParameterTag +forEachChildOfJSDocPropertyTag +yieldEachChildOfJSDocParameterTag +yieldEachChildOfJSDocPropertyTag +visitEachChildOfJSDocParameterTag +visitEachChildOfJSDocPropertyTag +createNodeArray +cloneNode +createToken +createIdentifier +createPrivateIdentifier +createQualifiedName +createComputedPropertyName +createDecorator +createEmptyStatement +createIfStatement +createDoStatement +createWhileStatement +createForStatement +createBreakStatement +createContinueStatement +createReturnStatement +createWithStatement +createSwitchStatement +createCaseBlock +createThrowStatement +createTryStatement +createCatchClause +createDebuggerStatement +createLabeledStatement +createExpressionStatement +createBlock +createVariableStatement +createVariableDeclaration +createVariableDeclarationList +createParameterDeclaration +createBindingElement +createMissingDeclaration +createFunctionDeclaration +createClassDeclaration +createClassExpression +createHeritageClause +createInterfaceDeclaration +createTypeAliasDeclaration +createEnumMember +createEnumDeclaration +createModuleBlock +createNotEmittedStatement +createNotEmittedTypeElement +createImportDeclaration +createExternalModuleReference +createNamespaceImport +createNamedImports +createExportAssignment +createNamespaceExportDeclaration +createNamespaceExport +createNamedExports +createExportSpecifier +createCallSignatureDeclaration +createConstructSignatureDeclaration +createConstructorDeclaration +createGetAccessorDeclaration +createSetAccessorDeclaration +createIndexSignatureDeclaration +createMethodSignatureDeclaration +createMethodDeclaration +createPropertySignatureDeclaration +createPropertyDeclaration +createSemicolonClassElement +createClassStaticBlockDeclaration +createOmittedExpression +createKeywordExpression +createStringLiteral +createNumericLiteral +createBigIntLiteral +createRegularExpressionLiteral +createNoSubstitutionTemplateLiteral +createBinaryExpression +createPrefixUnaryExpression +createPostfixUnaryExpression +createYieldExpression +createArrowFunction +createFunctionExpression +createAsExpression +createSatisfiesExpression +createConditionalExpression +createPropertyAccessExpression +createElementAccessExpression +createCallExpression +createNewExpression +createMetaProperty +createNonNullExpression +createSpreadElement +createTemplateExpression +createTemplateSpan +createTaggedTemplateExpression +createParenthesizedExpression +createArrayLiteralExpression +createObjectLiteralExpression +createSpreadAssignment +createPropertyAssignment +createShorthandPropertyAssignment +createDeleteExpression +createTypeOfExpression +createVoidExpression +createAwaitExpression +createTypeAssertion +createKeywordTypeNode +createUnionTypeNode +createIntersectionTypeNode +createConditionalTypeNode +createTypeOperatorNode +createInferTypeNode +createArrayTypeNode +createIndexedAccessTypeNode +createTypeReferenceNode +createExpressionWithTypeArguments +createLiteralTypeNode +createThisTypeNode +createTypePredicateNode +createImportAttribute +createImportAttributes +createTypeQueryNode +createMappedTypeNode +createTypeLiteralNode +createTupleTypeNode +createNamedTupleMember +createOptionalTypeNode +createRestTypeNode +createParenthesizedTypeNode +createFunctionTypeNode +createConstructorTypeNode +createTemplateHead +createTemplateMiddle +createTemplateTail +createTemplateLiteralTypeNode +createTemplateLiteralTypeSpan +createSyntheticExpression +createPartiallyEmittedExpression +createJsxElement +createJsxAttributes +createJsxNamespacedName +createJsxOpeningElement +createJsxSelfClosingElement +createJsxFragment +createJsxOpeningFragment +createJsxClosingFragment +createJsxAttribute +createJsxSpreadAttribute +createJsxClosingElement +createJsxExpression +createJsxText +createSyntaxList +createJSDoc +createJSDocTypeExpression +createJSDocNonNullableType +createJSDocNullableType +createJSDocAllType +createJSDocVariadicType +createJSDocOptionalType +createJSDocTypeTag +createJSDocUnknownTag +createJSDocTemplateTag +createJSDocReturnTag +createJSDocPublicTag +createJSDocPrivateTag +createJSDocProtectedTag +createJSDocReadonlyTag +createJSDocOverrideTag +createJSDocDeprecatedTag +createJSDocSeeTag +createJSDocImplementsTag +createJSDocAugmentsTag +createJSDocSatisfiesTag +createJSDocThrowsTag +createJSDocThisTag +createJSDocImportTag +createJSDocCallbackTag +createJSDocOverloadTag +createJSDocTypedefTag +createJSDocSignature +createJSDocNameReference +createModuleDeclaration +createImportEqualsDeclaration +createExportDeclaration +createImportTypeNode +createImportClause +createImportSpecifier +createJSDocText +createJSDocLink +createJSDocLinkPlain +createJSDocLinkCode +createTypeParameterDeclaration +createSyntheticReferenceExpression +createJSDocTypeLiteral +createForInStatement +createForOfStatement +createCaseClause +createDefaultClause +createObjectBindingPattern +createArrayBindingPattern +createJSDocParameterTag +createJSDocPropertyTag +updateQualifiedName +updateComputedPropertyName +updateDecorator +updateIfStatement +updateDoStatement +updateWhileStatement +updateForStatement +updateBreakStatement +updateContinueStatement +updateReturnStatement +updateWithStatement +updateSwitchStatement +updateCaseBlock +updateThrowStatement +updateTryStatement +updateCatchClause +updateLabeledStatement +updateExpressionStatement +updateBlock +updateVariableStatement +updateVariableDeclaration +updateVariableDeclarationList +updateParameterDeclaration +updateBindingElement +updateMissingDeclaration +updateFunctionDeclaration +updateClassDeclaration +updateClassExpression +updateHeritageClause +updateInterfaceDeclaration +updateTypeAliasDeclaration +updateEnumMember +updateEnumDeclaration +updateModuleBlock +updateImportDeclaration +updateExternalModuleReference +updateNamespaceImport +updateNamedImports +updateExportAssignment +updateNamespaceExportDeclaration +updateNamespaceExport +updateNamedExports +updateExportSpecifier +updateCallSignatureDeclaration +updateConstructSignatureDeclaration +updateConstructorDeclaration +updateGetAccessorDeclaration +updateSetAccessorDeclaration +updateIndexSignatureDeclaration +updateMethodSignatureDeclaration +updateMethodDeclaration +updatePropertySignatureDeclaration +updatePropertyDeclaration +updateClassStaticBlockDeclaration +updateBinaryExpression +updatePrefixUnaryExpression +updatePostfixUnaryExpression +updateYieldExpression +updateArrowFunction +updateFunctionExpression +updateAsExpression +updateSatisfiesExpression +updateConditionalExpression +updatePropertyAccessExpression +updateElementAccessExpression +updateCallExpression +updateNewExpression +updateMetaProperty +updateNonNullExpression +updateSpreadElement +updateTemplateExpression +updateTemplateSpan +updateTaggedTemplateExpression +updateParenthesizedExpression +updateArrayLiteralExpression +updateObjectLiteralExpression +updateSpreadAssignment +updatePropertyAssignment +updateShorthandPropertyAssignment +updateDeleteExpression +updateTypeOfExpression +updateVoidExpression +updateAwaitExpression +updateTypeAssertion +updateUnionTypeNode +updateIntersectionTypeNode +updateConditionalTypeNode +updateTypeOperatorNode +updateInferTypeNode +updateArrayTypeNode +updateIndexedAccessTypeNode +updateTypeReferenceNode +updateExpressionWithTypeArguments +updateLiteralTypeNode +updateTypePredicateNode +updateImportAttribute +updateImportAttributes +updateTypeQueryNode +updateMappedTypeNode +updateTypeLiteralNode +updateTupleTypeNode +updateNamedTupleMember +updateOptionalTypeNode +updateRestTypeNode +updateParenthesizedTypeNode +updateFunctionTypeNode +updateConstructorTypeNode +updateTemplateLiteralTypeNode +updateTemplateLiteralTypeSpan +updateSyntheticExpression +updatePartiallyEmittedExpression +updateJsxElement +updateJsxAttributes +updateJsxNamespacedName +updateJsxOpeningElement +updateJsxSelfClosingElement +updateJsxFragment +updateJsxAttribute +updateJsxSpreadAttribute +updateJsxClosingElement +updateJsxExpression +updateSyntaxList +updateJSDoc +updateJSDocTypeExpression +updateJSDocNonNullableType +updateJSDocNullableType +updateJSDocVariadicType +updateJSDocOptionalType +updateJSDocTypeTag +updateJSDocUnknownTag +updateJSDocTemplateTag +updateJSDocReturnTag +updateJSDocPublicTag +updateJSDocPrivateTag +updateJSDocProtectedTag +updateJSDocReadonlyTag +updateJSDocOverrideTag +updateJSDocDeprecatedTag +updateJSDocSeeTag +updateJSDocImplementsTag +updateJSDocAugmentsTag +updateJSDocSatisfiesTag +updateJSDocThrowsTag +updateJSDocThisTag +updateJSDocImportTag +updateJSDocCallbackTag +updateJSDocOverloadTag +updateJSDocTypedefTag +updateJSDocSignature +updateJSDocNameReference +updateModuleDeclaration +updateImportEqualsDeclaration +updateExportDeclaration +updateImportTypeNode +updateImportClause +updateImportSpecifier +updateJSDocLink +updateJSDocLinkPlain +updateJSDocLinkCode +updateTypeParameterDeclaration +updateSyntheticReferenceExpression +updateJSDocTypeLiteral +updateForInStatement +updateForOfStatement +updateCaseClause +updateDefaultClause +updateObjectBindingPattern +updateArrayBindingPattern +updateJSDocParameterTag +updateJSDocPropertyTag From 0e3d91506f9fa84830bad72785471852a30f1014 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Mon, 12 Oct 2026 14:31:19 -0700 Subject: [PATCH 2/6] add Nodefactory comparison --- tools/scripts/gen/apiDiff.mts | 1 + tsc/testdata/apiDiff.txt | 454 +++++++++------------------------- 2 files changed, 113 insertions(+), 342 deletions(-) diff --git a/tools/scripts/gen/apiDiff.mts b/tools/scripts/gen/apiDiff.mts index df2ed72d35fa4..298b3c732c457 100644 --- a/tools/scripts/gen/apiDiff.mts +++ b/tools/scripts/gen/apiDiff.mts @@ -32,6 +32,7 @@ const typeMappings = new Map([ ["Symbol", "Symbol"], ["Type", "Type"], ["Node", "Node"], + ["NodeFactory", "ts"], ["ts", "ts"], ]); diff --git a/tsc/testdata/apiDiff.txt b/tsc/testdata/apiDiff.txt index 54169e00508be..b823461231c15 100644 --- a/tsc/testdata/apiDiff.txt +++ b/tsc/testdata/apiDiff.txt @@ -28,7 +28,6 @@ Types not compared: - MinimalResolutionCacheHost - CompilerHost - SourceMapSource -- NodeFactory - CoreTransformationContext - TransformationContext - TransformationResult @@ -344,6 +343,117 @@ isUnionOrIntersection ## Node methods missing from async Node (0) ## +# NodeFactory (old) methods compared to ts (new). +## (342) NodeFactory methods matched in async ts ## + +## NodeFactory methods missing from async ts (105) ## +createAdd +createAssertClause +createAssertEntry +createAssignment +createBitwiseAnd +createBitwiseNot +createBitwiseOr +createBitwiseXor +createBundle +createCallChain +createCallSignature +createComma +createCommaListExpression +createConstructSignature +createDivide +createElementAccessChain +createEquality +createExponent +createExportDefault +createExternalModuleExport +createFalse +createGreaterThan +createGreaterThanEquals +createImmediatelyInvokedArrowFunction +createImmediatelyInvokedFunctionExpression +createImportTypeAssertionContainer +createIndexSignature +createInequality +createJSDocAuthorTag +createJSDocClassTag +createJSDocComment +createJSDocEnumTag +createJSDocFunctionType +createJSDocMemberName +createJSDocNamepathType +createJSDocUnknownType +createJsxJsxClosingFragment +createLeftShift +createLessThan +createLessThanEquals +createLogicalAnd +createLogicalNot +createLogicalOr +createLoopVariable +createMethodSignature +createModifier +createModifiersFromModifierFlags +createModulo +createMultiply +createNonNullChain +createNull +createParenthesizedType +createPostfixDecrement +createPostfixIncrement +createPrefixDecrement +createPrefixIncrement +createPrefixMinus +createPrefixPlus +createPropertyAccessChain +createPropertySignature +createRightShift +createStrictEquality +createStrictInequality +createStringLiteralFromNode +createSubtract +createSuper +createTempVariable +createTemplateLiteralType +createThis +createTrue +createUniqueName +createUniquePrivateName +createUnsignedRightShift +createVoidZero +getGeneratedNameForNode +getGeneratedPrivateNameForNode +replaceDecoratorsAndModifiers +replaceModifiers +replacePropertyName +restoreOuterExpressions +updateAssertClause +updateAssertEntry +updateBundle +updateCallChain +updateCallSignature +updateCommaListExpression +updateConstructSignature +updateElementAccessChain +updateImportTypeAssertionContainer +updateIndexSignature +updateJSDocAuthorTag +updateJSDocClassTag +updateJSDocComment +updateJSDocEnumTag +updateJSDocFunctionType +updateJSDocMemberName +updateJSDocNamepathType +updateJSDocText +updateJsxText +updateMethodSignature +updateNonNullChain +updateParenthesizedType +updatePropertyAccessChain +updatePropertySignature +updateTemplateLiteralType + + # ts (old) methods compared to ts (new). ## (275) ts methods matched in async ts ## @@ -819,7 +929,7 @@ getChildren getFirstToken getLastToken -## New ts methods in async API (545) ## +## New ts methods in async API (205) ## isRemoteNode getSymbol isUnionType @@ -998,370 +1108,30 @@ yieldEachChildOfJSDocParameterTag yieldEachChildOfJSDocPropertyTag visitEachChildOfJSDocParameterTag visitEachChildOfJSDocPropertyTag -createNodeArray cloneNode -createToken -createIdentifier -createPrivateIdentifier -createQualifiedName -createComputedPropertyName -createDecorator -createEmptyStatement -createIfStatement -createDoStatement -createWhileStatement -createForStatement -createBreakStatement -createContinueStatement -createReturnStatement -createWithStatement -createSwitchStatement -createCaseBlock -createThrowStatement -createTryStatement -createCatchClause -createDebuggerStatement -createLabeledStatement -createExpressionStatement -createBlock -createVariableStatement -createVariableDeclaration -createVariableDeclarationList -createParameterDeclaration -createBindingElement createMissingDeclaration -createFunctionDeclaration -createClassDeclaration -createClassExpression -createHeritageClause -createInterfaceDeclaration -createTypeAliasDeclaration -createEnumMember -createEnumDeclaration -createModuleBlock -createNotEmittedStatement -createNotEmittedTypeElement -createImportDeclaration -createExternalModuleReference -createNamespaceImport -createNamedImports -createExportAssignment -createNamespaceExportDeclaration -createNamespaceExport -createNamedExports -createExportSpecifier createCallSignatureDeclaration createConstructSignatureDeclaration -createConstructorDeclaration -createGetAccessorDeclaration -createSetAccessorDeclaration createIndexSignatureDeclaration createMethodSignatureDeclaration -createMethodDeclaration createPropertySignatureDeclaration -createPropertyDeclaration -createSemicolonClassElement -createClassStaticBlockDeclaration -createOmittedExpression createKeywordExpression -createStringLiteral -createNumericLiteral -createBigIntLiteral -createRegularExpressionLiteral -createNoSubstitutionTemplateLiteral -createBinaryExpression -createPrefixUnaryExpression -createPostfixUnaryExpression -createYieldExpression -createArrowFunction -createFunctionExpression -createAsExpression -createSatisfiesExpression -createConditionalExpression -createPropertyAccessExpression -createElementAccessExpression -createCallExpression -createNewExpression -createMetaProperty -createNonNullExpression -createSpreadElement -createTemplateExpression -createTemplateSpan -createTaggedTemplateExpression -createParenthesizedExpression -createArrayLiteralExpression -createObjectLiteralExpression -createSpreadAssignment -createPropertyAssignment -createShorthandPropertyAssignment -createDeleteExpression -createTypeOfExpression -createVoidExpression -createAwaitExpression -createTypeAssertion -createKeywordTypeNode -createUnionTypeNode -createIntersectionTypeNode -createConditionalTypeNode -createTypeOperatorNode -createInferTypeNode -createArrayTypeNode -createIndexedAccessTypeNode -createTypeReferenceNode -createExpressionWithTypeArguments -createLiteralTypeNode -createThisTypeNode -createTypePredicateNode -createImportAttribute -createImportAttributes -createTypeQueryNode -createMappedTypeNode -createTypeLiteralNode -createTupleTypeNode -createNamedTupleMember -createOptionalTypeNode -createRestTypeNode createParenthesizedTypeNode -createFunctionTypeNode -createConstructorTypeNode -createTemplateHead -createTemplateMiddle -createTemplateTail createTemplateLiteralTypeNode -createTemplateLiteralTypeSpan createSyntheticExpression -createPartiallyEmittedExpression -createJsxElement -createJsxAttributes -createJsxNamespacedName -createJsxOpeningElement -createJsxSelfClosingElement -createJsxFragment -createJsxOpeningFragment createJsxClosingFragment -createJsxAttribute -createJsxSpreadAttribute -createJsxClosingElement -createJsxExpression -createJsxText createSyntaxList createJSDoc -createJSDocTypeExpression -createJSDocNonNullableType -createJSDocNullableType -createJSDocAllType -createJSDocVariadicType -createJSDocOptionalType -createJSDocTypeTag -createJSDocUnknownTag -createJSDocTemplateTag -createJSDocReturnTag -createJSDocPublicTag -createJSDocPrivateTag -createJSDocProtectedTag -createJSDocReadonlyTag -createJSDocOverrideTag -createJSDocDeprecatedTag -createJSDocSeeTag -createJSDocImplementsTag -createJSDocAugmentsTag -createJSDocSatisfiesTag -createJSDocThrowsTag -createJSDocThisTag -createJSDocImportTag -createJSDocCallbackTag -createJSDocOverloadTag -createJSDocTypedefTag -createJSDocSignature -createJSDocNameReference -createModuleDeclaration -createImportEqualsDeclaration -createExportDeclaration -createImportTypeNode -createImportClause -createImportSpecifier -createJSDocText -createJSDocLink -createJSDocLinkPlain -createJSDocLinkCode -createTypeParameterDeclaration createSyntheticReferenceExpression -createJSDocTypeLiteral -createForInStatement -createForOfStatement -createCaseClause -createDefaultClause -createObjectBindingPattern -createArrayBindingPattern -createJSDocParameterTag -createJSDocPropertyTag -updateQualifiedName -updateComputedPropertyName -updateDecorator -updateIfStatement -updateDoStatement -updateWhileStatement -updateForStatement -updateBreakStatement -updateContinueStatement -updateReturnStatement -updateWithStatement -updateSwitchStatement -updateCaseBlock -updateThrowStatement -updateTryStatement -updateCatchClause -updateLabeledStatement -updateExpressionStatement -updateBlock -updateVariableStatement -updateVariableDeclaration -updateVariableDeclarationList -updateParameterDeclaration -updateBindingElement updateMissingDeclaration -updateFunctionDeclaration -updateClassDeclaration -updateClassExpression -updateHeritageClause -updateInterfaceDeclaration -updateTypeAliasDeclaration -updateEnumMember -updateEnumDeclaration -updateModuleBlock -updateImportDeclaration -updateExternalModuleReference -updateNamespaceImport -updateNamedImports -updateExportAssignment -updateNamespaceExportDeclaration -updateNamespaceExport -updateNamedExports -updateExportSpecifier updateCallSignatureDeclaration updateConstructSignatureDeclaration -updateConstructorDeclaration -updateGetAccessorDeclaration -updateSetAccessorDeclaration updateIndexSignatureDeclaration updateMethodSignatureDeclaration -updateMethodDeclaration updatePropertySignatureDeclaration -updatePropertyDeclaration -updateClassStaticBlockDeclaration -updateBinaryExpression -updatePrefixUnaryExpression -updatePostfixUnaryExpression -updateYieldExpression -updateArrowFunction -updateFunctionExpression -updateAsExpression -updateSatisfiesExpression -updateConditionalExpression -updatePropertyAccessExpression -updateElementAccessExpression -updateCallExpression -updateNewExpression -updateMetaProperty -updateNonNullExpression -updateSpreadElement -updateTemplateExpression -updateTemplateSpan -updateTaggedTemplateExpression -updateParenthesizedExpression -updateArrayLiteralExpression -updateObjectLiteralExpression -updateSpreadAssignment -updatePropertyAssignment -updateShorthandPropertyAssignment -updateDeleteExpression -updateTypeOfExpression -updateVoidExpression -updateAwaitExpression -updateTypeAssertion -updateUnionTypeNode -updateIntersectionTypeNode -updateConditionalTypeNode -updateTypeOperatorNode -updateInferTypeNode -updateArrayTypeNode -updateIndexedAccessTypeNode -updateTypeReferenceNode -updateExpressionWithTypeArguments -updateLiteralTypeNode -updateTypePredicateNode -updateImportAttribute -updateImportAttributes -updateTypeQueryNode -updateMappedTypeNode -updateTypeLiteralNode -updateTupleTypeNode -updateNamedTupleMember -updateOptionalTypeNode -updateRestTypeNode updateParenthesizedTypeNode -updateFunctionTypeNode -updateConstructorTypeNode updateTemplateLiteralTypeNode -updateTemplateLiteralTypeSpan updateSyntheticExpression -updatePartiallyEmittedExpression -updateJsxElement -updateJsxAttributes -updateJsxNamespacedName -updateJsxOpeningElement -updateJsxSelfClosingElement -updateJsxFragment -updateJsxAttribute -updateJsxSpreadAttribute -updateJsxClosingElement -updateJsxExpression updateSyntaxList updateJSDoc -updateJSDocTypeExpression -updateJSDocNonNullableType -updateJSDocNullableType -updateJSDocVariadicType -updateJSDocOptionalType -updateJSDocTypeTag -updateJSDocUnknownTag -updateJSDocTemplateTag -updateJSDocReturnTag -updateJSDocPublicTag -updateJSDocPrivateTag -updateJSDocProtectedTag -updateJSDocReadonlyTag -updateJSDocOverrideTag -updateJSDocDeprecatedTag -updateJSDocSeeTag -updateJSDocImplementsTag -updateJSDocAugmentsTag -updateJSDocSatisfiesTag -updateJSDocThrowsTag -updateJSDocThisTag -updateJSDocImportTag -updateJSDocCallbackTag -updateJSDocOverloadTag -updateJSDocTypedefTag -updateJSDocSignature -updateJSDocNameReference -updateModuleDeclaration -updateImportEqualsDeclaration -updateExportDeclaration -updateImportTypeNode -updateImportClause -updateImportSpecifier -updateJSDocLink -updateJSDocLinkPlain -updateJSDocLinkCode -updateTypeParameterDeclaration updateSyntheticReferenceExpression -updateJSDocTypeLiteral -updateForInStatement -updateForOfStatement -updateCaseClause -updateDefaultClause -updateObjectBindingPattern -updateArrayBindingPattern -updateJSDocParameterTag -updateJSDocPropertyTag From 99db89d6d0d7d5004058b195dbfe6a214320a94b Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Tue, 13 Oct 2026 23:38:31 -0700 Subject: [PATCH 3/6] allow old structures to be matched to multiple new --- tools/scripts/gen/apiDiff.mts | 60 ++++++++++++++++++++--------------- tsc/testdata/apiDiff.txt | 17 ++++------ 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/tools/scripts/gen/apiDiff.mts b/tools/scripts/gen/apiDiff.mts index 298b3c732c457..9b5e6bac972c7 100644 --- a/tools/scripts/gen/apiDiff.mts +++ b/tools/scripts/gen/apiDiff.mts @@ -18,7 +18,7 @@ const newApiEntryPoints = [ "src/ast/clone.ts", ].map(file => path.join(newApiPackageDirectory, file)); const outputPath = path.join(repoRoot, "tsc", "testdata", "apiDiff.txt"); -const typeMappings = new Map([ +const typeMappings = new Map([ ["TypeChecker", "Checker"], ["BuilderProgram", "Program"], ["Program", "Program"], @@ -33,7 +33,7 @@ const typeMappings = new Map([ ["Type", "Type"], ["Node", "Node"], ["NodeFactory", "ts"], - ["ts", "ts"], + ["ts", ["ts", "API"]], ]); const typescriptVersion = JSON.parse( @@ -58,37 +58,42 @@ const report: string[] = [ "# New API: public package entry points", ]; -const comparisons = [...typeMappings].map(([oldType, newType]) => { +const comparisons = [...typeMappings].map(([oldType, newTypes]) => { const oldMethods = oldApiTypes.get(oldType)!; - const newMethods = newApiTypes.get(newType)!; const acceptedChanges = acceptedDiffs.get(oldType) ?? new Map(); + let missing: string[] = [...oldMethods.keys()]; const present: string[] = []; - const missing: string[] = []; - for (const method of oldMethods) { - if (newMethods[0].has(method)) { - present.push(method); - newMethods[0].delete(method); - newMethods[1].add(method); - } - else if (newMethods[1].has(method)) { - present.push(method); - } - else if (acceptedChanges.has(method)) { - present.push(method); - const [newType, newMethodName] = acceptedChanges.get(method)!.split("."); - const actualNewType = newApiTypes.get(newType); - if (actualNewType) { - actualNewType[0].delete(newMethodName); - actualNewType[1].add(method); + const newTypeArray = Array.isArray(newTypes) ? newTypes : [newTypes]; + for (const newType of newTypeArray) { + const currMissing: string[] = []; + const newMethods = newApiTypes.get(newType)!; + for (const method of missing) { + if (newMethods[0].has(method)) { + present.push(method); + newMethods[0].delete(method); + newMethods[1].add(method); + } + else if (newMethods[1].has(method)) { + present.push(method); + } + else if (acceptedChanges.has(method)) { + present.push(method); + const [newType, newMethodName] = acceptedChanges.get(method)!.split("."); + const actualNewType = newApiTypes.get(newType); + if (actualNewType) { + actualNewType[0].delete(newMethodName); + actualNewType[1].add(method); + } + } + else { + currMissing.push(method); } } - else { - missing.push(method); - } + missing = currMissing; } return { oldType, - newType, + newTypes, present: present.sort(), missing: missing.sort(), }; @@ -105,7 +110,8 @@ report.push( ); for (const comparison of comparisons) { - const { oldType, newType, present, missing } = comparison; + const { oldType, newTypes, present, missing } = comparison; + const newType = Array.isArray(newTypes) ? newTypes.join(", ") : newTypes; report.push( "", `# ${oldType} (old) methods compared to ${newType} (new).`, @@ -117,6 +123,8 @@ for (const comparison of comparisons) { ); } +report.push("\n\n # New Methods in async API (temporarily reported for increased ease of matching)"); + for (const [newType, newMethods] of newApiTypes) { report.push( `## New ${newType} methods in async API (${newMethods[0].size}) ##`, diff --git a/tsc/testdata/apiDiff.txt b/tsc/testdata/apiDiff.txt index b823461231c15..76df569c3f6c0 100644 --- a/tsc/testdata/apiDiff.txt +++ b/tsc/testdata/apiDiff.txt @@ -454,10 +454,10 @@ updatePropertySignature updateTemplateLiteralType -# ts (old) methods compared to ts (new). -## (275) ts methods matched in async ts ## +# ts (old) methods compared to ts, API (new). +## (278) ts methods matched in async ts, API ## -## ts methods missing from async ts (213) ## +## ts methods missing from async ts, API (210) ## addEmitHelper addEmitHelpers addSyntheticLeadingComment @@ -482,7 +482,6 @@ createLanguageService createLanguageServiceSourceFile createModuleResolutionCache createPrinter -createProgram createSemanticDiagnosticsBuilderProgram createSolutionBuilder createSolutionBuilderHost @@ -661,8 +660,6 @@ textSpanOverlapsWith toEditorSettings transform transpile -transpileDeclaration -transpileModule updateLanguageServiceSourceFile validateLocaleAndSetLanguage visitCommaListElements @@ -672,6 +669,9 @@ visitLexicalEnvironment visitParameterList walkUpBindingElementsAndPatterns + + + # New Methods in async API (temporarily reported for increased ease of matching) ## New ConditionalType methods in async API (4) ## getCheckType getExtendsType @@ -758,7 +758,7 @@ getTarget ## New UnionOrIntersectionType methods in async API (1) ## getTypes -## New API methods in async API (23) ## +## New API methods in async API (20) ## getSymbol fromLSPConnection batchContext @@ -769,9 +769,7 @@ createBuildOrchestrator createSourceFile createSourceFileFromFile retainSourceFile -transpileModule transpileModuleFromFile -transpileDeclaration transpileDeclarationFromFile createSnapshot getCurrentLanguageServerSnapshot @@ -781,7 +779,6 @@ clearSourceFileCache runWithTemporaryFileUpdate getTimingInfo resetTimingInfo -createProgram ## New RetainedSourceFile methods in async API (1) ## dispose From 2e418dde211f6a33e690f962d5d2a938a280cb83 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Wed, 4 Nov 2026 15:45:54 -0800 Subject: [PATCH 4/6] update with recent changes --- tsc/testdata/apiAccepted.txt | 10 ++++++++- tsc/testdata/apiDiff.txt | 41 ++++++++++-------------------------- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/tsc/testdata/apiAccepted.txt b/tsc/testdata/apiAccepted.txt index 7f27b957d80d5..ace7f581baed7 100644 --- a/tsc/testdata/apiAccepted.txt +++ b/tsc/testdata/apiAccepted.txt @@ -1,7 +1,15 @@ originalType.MethodName|newType.MethodName|reason (will be discarded in parsing) -If the original TypeChecker.tryGetMemberInModuleExports|Checker.getMemberInModuleExports|rename +TypeChecker.getAugmentedPropertiesOfType|| use `Type.getApparentProperties()` instead +Program.getTypeChecker|| removed +Project.containsFile|| same as `Program` method +Project.getFileNames|| same as `Program` method +Project.getRootFiles||same as `Program` method +Project.hasRoots|| same as `Program` method +Project.isRoot|| same as `Program` method +Project.hasConfigFile|| same as `Program` method +Project.getSourceFile|| same as `Program` method ts.parseCommandLine|API.parseCommandLine| ts.parseJsonConfigFileContent|API.parseJsonConfigFileContent| ts.parseConfigFileTextToJson|API.readConfigFile|the same minus error handling diff --git a/tsc/testdata/apiDiff.txt b/tsc/testdata/apiDiff.txt index 76df569c3f6c0..6663c9e07eb69 100644 --- a/tsc/testdata/apiDiff.txt +++ b/tsc/testdata/apiDiff.txt @@ -66,27 +66,15 @@ Types not compared: # TypeChecker (old) methods compared to Checker (new). -## (60) TypeChecker methods matched in async Checker ## +## (72) TypeChecker methods matched in async Checker ## -## TypeChecker methods missing from async Checker (29) ## -getAmbientModules -getAugmentedPropertiesOfType -getBigIntLiteralType -getFalseType -getJsxIntrinsicTagNamesAt -getNullableType -getNumberLiteralType -getPrivateIdentifierPropertyOfType -getPropertySymbolOfDestructuringAssignment +## TypeChecker methods missing from async Checker (17) ## getRootSymbols -getStringLiteralType getSymbolOfExpando getSymbolsOfParameterPropertyDeclaration -getTrueType getTypeArgumentsForResolvedSignature getTypeOfAssignmentPattern indexInfoToIndexSignatureDeclaration -isImplementationOfOverload isOptionalParameter isValidPropertyAccess runWithCancellationToken @@ -111,9 +99,9 @@ getSourceFiles # Program (old) methods compared to Program (new). -## (11) Program methods matched in async Program ## +## (12) Program methods matched in async Program ## -## Program methods missing from async Program (12) ## +## Program methods missing from async Program (11) ## getIdentifierCount getInstantiationCount getNodeCount @@ -124,7 +112,6 @@ getResolvedProjectReferences getRootFileNames getSourceFiles getSymbolCount -getTypeChecker getTypeCount @@ -136,13 +123,12 @@ getNextInvalidatedProject # Project (old) methods compared to Project (new). -## (0) Project methods matched in async Project ## +## (7) Project methods matched in async Project ## -## Project methods missing from async Project (61) ## +## Project methods missing from async Project (54) ## addMissingFileRoot addRoot close -containsFile containsScriptInfo directoryExists disableLanguageService @@ -161,14 +147,12 @@ getDefaultLibFileName getDirectories getExcludedFiles getExternalFiles -getFileNames getGlobalProjectErrors getLanguageService getNewLine getProjectName getProjectReferences getProjectVersion -getRootFiles getRootScriptInfos getScriptFileNames getScriptInfo @@ -177,16 +161,12 @@ getScriptInfos getScriptKind getScriptSnapshot getScriptVersion -getSourceFile getTypeAcquisition -hasConfigFile -hasRoots installPackage isClosed isJsOnlyProject isKnownTypesPackageName isNonTsProject -isRoot log readDirectory readFile @@ -455,9 +435,9 @@ updateTemplateLiteralType # ts (old) methods compared to ts, API (new). -## (278) ts methods matched in async ts, API ## +## (279) ts methods matched in async ts, API ## -## ts methods missing from async ts, API (210) ## +## ts methods missing from async ts, API (209) ## addEmitHelper addEmitHelpers addSyntheticLeadingComment @@ -567,7 +547,6 @@ isAutoAccessorPropertyDeclaration isBuildCommand isBundle isCallChain -isCaseOrDefaultClause isClassElement isClassLike isClassOrTypeElement @@ -926,7 +905,7 @@ getChildren getFirstToken getLastToken -## New ts methods in async API (205) ## +## New ts methods in async API (207) ## isRemoteNode getSymbol isUnionType @@ -955,6 +934,7 @@ fileNameToDocumentURI createFileSystem createFileSystemWithLib createFileSystemLayer +createFileSystemFromSnapshot validateSymbolOwner validateSymbolResponse resolveFileName @@ -965,6 +945,7 @@ getTouchingToken findNextToken findPrecedingToken getTokenPosOfNode +getPooledScannersForTesting getChildren getFirstToken getLastToken From 94ad0c7e991ae02a190f57e64d7cd171d28f3d98 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Wed, 4 Nov 2026 18:56:51 -0800 Subject: [PATCH 5/6] add change --- tsc/testdata/apiAccepted.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tsc/testdata/apiAccepted.txt b/tsc/testdata/apiAccepted.txt index ace7f581baed7..b6c233e403dee 100644 --- a/tsc/testdata/apiAccepted.txt +++ b/tsc/testdata/apiAccepted.txt @@ -12,6 +12,5 @@ Project.hasConfigFile|| same as `Program` method Project.getSourceFile|| same as `Program` method ts.parseCommandLine|API.parseCommandLine| ts.parseJsonConfigFileContent|API.parseJsonConfigFileContent| -ts.parseConfigFileTextToJson|API.readConfigFile|the same minus error handling ts.readConfigFile|API.readConfigFile| ts.parseJsonSourceFileConfigFileContent|API.parseConfigFile| From 5bc55861f704a57ca6bf67db88e6b8a335a31493 Mon Sep 17 00:00:00 2001 From: Isabel Duan Date: Thu, 5 Nov 2026 15:37:51 -0800 Subject: [PATCH 6/6] update with main --- tools/scripts/gen/apiDiff.mts | 608 +++++++++++++++++----------------- tsc/testdata/apiAccepted.txt | 1 + tsc/testdata/apiDiff.txt | 12 +- 3 files changed, 310 insertions(+), 311 deletions(-) diff --git a/tools/scripts/gen/apiDiff.mts b/tools/scripts/gen/apiDiff.mts index 9b5e6bac972c7..54ed5ba5570c8 100644 --- a/tools/scripts/gen/apiDiff.mts +++ b/tools/scripts/gen/apiDiff.mts @@ -1,304 +1,304 @@ -import fs from "node:fs"; -import path from "node:path"; -import ts from "typescript"; -import { repoRoot } from "./utils.mts"; - -const oldApiPath = path.join(repoRoot, "node_modules", "typescript", "lib", "typescript.d.ts"); -const newApiPackageDirectory = path.join(repoRoot, "packages", "typescript"); -const newApiEntryPoints = [ - "src/api/async/api.ts", - "src/api/fs.ts", - "src/api/proto.ts", - "src/ast/index.ts", - "src/ast/is.ts", - "src/ast/factory.generated.ts", - "src/ast/utils.ts", - "src/ast/scanner.ts", - "src/ast/visitor.ts", - "src/ast/clone.ts", -].map(file => path.join(newApiPackageDirectory, file)); -const outputPath = path.join(repoRoot, "tsc", "testdata", "apiDiff.txt"); -const typeMappings = new Map([ - ["TypeChecker", "Checker"], - ["BuilderProgram", "Program"], - ["Program", "Program"], - ["SolutionBuilder", "BuildOrchestrator"], - ["Project", "Project"], - ["LanguageService", "Project"], - ["Scanner", "Scanner"], - ["Printer", "Printer"], - ["Signature", "Signature"], - ["SourceFile", "SourceFile"], - ["Symbol", "Symbol"], - ["Type", "Type"], - ["Node", "Node"], - ["NodeFactory", "ts"], - ["ts", ["ts", "API"]], -]); - -const typescriptVersion = JSON.parse( - fs.readFileSync(path.join(repoRoot, "node_modules", "typescript", "package.json"), "utf8"), -).version as string; -const oldApiSourceFiles = [createSourceFile(oldApiPath)]; -const newApiProgram = createNewApiProgram(); -const newApiChecker = newApiProgram.getTypeChecker(); -const newApiExports = getEntryPointExports(newApiProgram, newApiChecker, newApiEntryPoints); - -const oldApiTypes = getTypesWithMethods(oldApiSourceFiles, visitOld); -oldApiTypes.set("ts", getNamespaceFunctions(oldApiSourceFiles, "ts")); - -const newApiTypes = getExportedTypesWithMethods(newApiExports); -newApiTypes.set("ts", [getExportedTopLevelFunctions(newApiExports, newApiChecker), new Set()]); - -const acceptedDiffs = getAcceptedDiffs(); - -const report: string[] = [ - "# This report is generated by tools/scripts/gen/apidiff.mts.", - `# Old API: TypeScript ${typescriptVersion} (node_modules/typescript/lib/typescript.d.ts)`, - "# New API: public package entry points", -]; - -const comparisons = [...typeMappings].map(([oldType, newTypes]) => { - const oldMethods = oldApiTypes.get(oldType)!; - const acceptedChanges = acceptedDiffs.get(oldType) ?? new Map(); - let missing: string[] = [...oldMethods.keys()]; - const present: string[] = []; - const newTypeArray = Array.isArray(newTypes) ? newTypes : [newTypes]; - for (const newType of newTypeArray) { - const currMissing: string[] = []; - const newMethods = newApiTypes.get(newType)!; - for (const method of missing) { - if (newMethods[0].has(method)) { - present.push(method); - newMethods[0].delete(method); - newMethods[1].add(method); - } - else if (newMethods[1].has(method)) { - present.push(method); - } - else if (acceptedChanges.has(method)) { - present.push(method); - const [newType, newMethodName] = acceptedChanges.get(method)!.split("."); - const actualNewType = newApiTypes.get(newType); - if (actualNewType) { - actualNewType[0].delete(newMethodName); - actualNewType[1].add(method); - } - } - else { - currMissing.push(method); - } - } - missing = currMissing; - } - return { - oldType, - newTypes, - present: present.sort(), - missing: missing.sort(), - }; -}); - -report.push( - `Types not compared:`, -); -for (const [type, _] of oldApiTypes) { - typeMappings.has(type) || report.push(`- ${type}`); -} -report.push( - "", -); - -for (const comparison of comparisons) { - const { oldType, newTypes, present, missing } = comparison; - const newType = Array.isArray(newTypes) ? newTypes.join(", ") : newTypes; - report.push( - "", - `# ${oldType} (old) methods compared to ${newType} (new).`, - `## (${present.length}) ${oldType} methods matched in async ${newType} ##`, - "", - `## ${oldType} methods missing from async ${newType} (${missing.length}) ##`, - ...missing, - "", - ); -} - -report.push("\n\n # New Methods in async API (temporarily reported for increased ease of matching)"); - -for (const [newType, newMethods] of newApiTypes) { - report.push( - `## New ${newType} methods in async API (${newMethods[0].size}) ##`, - ...newMethods[0], - "", - ); -} - -fs.writeFileSync(outputPath, report.join("\n")); - -function createSourceFile(file: string): ts.SourceFile { - return ts.createSourceFile( - file, - fs.readFileSync(file, "utf8"), - ts.ScriptTarget.Latest, - true, - ); -} - -function createNewApiProgram(): ts.Program { - const configPath = path.join(newApiPackageDirectory, "tsconfig.json"); - const configFile = ts.readConfigFile(configPath, ts.sys.readFile); - if (configFile.error) { - throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n")); - } - const config = ts.parseJsonConfigFileContent(configFile.config, ts.sys, newApiPackageDirectory, { noEmit: true }, configPath); - if (config.errors.length > 0) { - throw new Error(config.errors.map(error => ts.flattenDiagnosticMessageText(error.messageText, "\n")).join("\n")); - } - return ts.createProgram({ - rootNames: config.fileNames, - options: config.options, - projectReferences: config.projectReferences, - }); -} - -type EntryPointExports = ReadonlyMap>; - -function getEntryPointExports(program: ts.Program, checker: ts.TypeChecker, entryPoints: readonly string[]): EntryPointExports { - const exports = new Map>(); - for (const entryPoint of entryPoints) { - const sourceFile = program.getSourceFile(entryPoint); - if (!sourceFile) throw new Error(`Could not find API entry point ${entryPoint}`); - const moduleSymbol = checker.getSymbolAtLocation(sourceFile); - if (!moduleSymbol) throw new Error(`Could not resolve API entry point ${entryPoint}`); - for (const exportedSymbol of checker.getExportsOfModule(moduleSymbol)) { - const symbols = exports.get(exportedSymbol.name) ?? new Set(); - symbols.add(resolveAlias(exportedSymbol, checker)); - exports.set(exportedSymbol.name, symbols); - } - } - return exports; -} - -function resolveAlias(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol { - return symbol.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol; -} - -function getTypesWithMethods(sourceFiles: readonly ts.SourceFile[], visitNode: (node: ts.Node, types: Map) => void): Map { - const types = new Map(); - for (const sourceFile of sourceFiles) { - visit(sourceFile); - } - return types; - - function visit(node: ts.Node): void { - visitNode(node, types); - ts.forEachChild(node, visit); - } -} - -function getAcceptedDiffs(): Map> { - const diffs = new Map>(); - const contents = fs.readFileSync(path.join(repoRoot, "tsc", "testdata", "apiAccepted.txt"), "utf-8").split("\n"); - contents.slice(2).forEach(line => { - const [oldMethod, newMethod, _] = line.split("|"); - const [oldType, oldMethodName] = oldMethod.split("."); - if (!diffs.has(oldType)) diffs.set(oldType, new Map()); - diffs.get(oldType)!.set(oldMethodName, newMethod); - }); - return diffs; -} - -function visitOld(node: ts.Node, types: Map>): void { - if ((ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.name) { - const methods = types.get(node.name.text) ?? new Set(); - for (const member of node.members) { - if ( - (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) - && !hasModifier(member, ts.SyntaxKind.PrivateKeyword) - && !hasModifier(member, ts.SyntaxKind.ProtectedKeyword) - ) { - const name = getPropertyName(member.name); - if (name !== undefined) methods.add(name); - } - } - if (methods.size > 0) types.set(node.name.text, methods); - } -} - -function getExportedTypesWithMethods(exports: EntryPointExports): Map, seen: Set]> { - const types = new Map, seen: Set]>(); - for (const [exportName, symbols] of exports) { - const methods = new Set(); - for (const symbol of symbols) { - for (const declaration of symbol.declarations ?? []) { - if (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) { - addPublicMethods(declaration.members, methods); - } - } - } - if (methods.size > 0) types.set(exportName, [methods, new Set()]); - } - return types; -} - -function addPublicMethods(members: ts.NodeArray, methods: Set): void { - for (const member of members) { - if ( - (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) - && !hasModifier(member, ts.SyntaxKind.PrivateKeyword) - && !hasModifier(member, ts.SyntaxKind.ProtectedKeyword) - ) { - const name = getPropertyName(member.name); - if (name !== undefined) methods.add(name); - } - } -} - -function getNamespaceFunctions(sourceFiles: readonly ts.SourceFile[], namespace: string): Set { - const functions = new Set(); - for (const sourceFile of sourceFiles) { - for (const statement of sourceFile.statements) { - if ( - ts.isModuleDeclaration(statement) - && statement.name.text === namespace - && statement.body - && ts.isModuleBlock(statement.body) - ) { - for (const member of statement.body.statements) { - if (ts.isFunctionDeclaration(member) && member.name) { - functions.add(member.name.text); - } - } - } - } - } - return functions; -} - -function getExportedTopLevelFunctions(exports: EntryPointExports, checker: ts.TypeChecker): Set { - const functions = new Set(); - for (const [exportName, symbols] of exports) { - for (const symbol of symbols) { - const declaration = symbol.valueDeclaration; - if ( - declaration - && checker.getTypeOfSymbolAtLocation(symbol, declaration).getCallSignatures().length > 0 - ) { - functions.add(exportName); - break; - } - } - } - return functions; -} - -function hasModifier(node: ts.Node, kind: ts.SyntaxKind): boolean { - return ts.canHaveModifiers(node) && ts.getModifiers(node)?.some(modifier => modifier.kind === kind) === true; -} - -function getPropertyName(name: ts.PropertyName): string | undefined { - if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) { - return name.text; - } - return undefined; -} +import fs from "node:fs"; +import path from "node:path"; +import ts from "typescript"; +import { repoRoot } from "./utils.mts"; + +const oldApiPath = path.join(repoRoot, "node_modules", "typescript", "lib", "typescript.d.ts"); +const newApiPackageDirectory = path.join(repoRoot, "packages", "typescript"); +const newApiEntryPoints = [ + "src/api/async/api.ts", + "src/api/fs.ts", + "src/api/proto.ts", + "src/ast/index.ts", + "src/ast/is.ts", + "src/ast/factory.generated.ts", + "src/ast/utils.ts", + "src/ast/scanner.ts", + "src/ast/visitor.ts", + "src/ast/clone.ts", +].map(file => path.join(newApiPackageDirectory, file)); +const outputPath = path.join(repoRoot, "tsc", "testdata", "apiDiff.txt"); +const typeMappings = new Map([ + ["TypeChecker", "Checker"], + ["BuilderProgram", "Program"], + ["Program", "Program"], + ["SolutionBuilder", "BuildOrchestrator"], + ["Project", "Project"], + ["LanguageService", "Project"], + ["Scanner", "Scanner"], + ["Printer", "Printer"], + ["Signature", "Signature"], + ["SourceFile", "SourceFile"], + ["Symbol", "Symbol"], + ["Type", ["Type", "ts"]], + ["Node", "Node"], + ["NodeFactory", "ts"], + ["ts", ["ts", "API"]], +]); + +const typescriptVersion = JSON.parse( + fs.readFileSync(path.join(repoRoot, "node_modules", "typescript", "package.json"), "utf8"), +).version as string; +const oldApiSourceFiles = [createSourceFile(oldApiPath)]; +const newApiProgram = createNewApiProgram(); +const newApiChecker = newApiProgram.getTypeChecker(); +const newApiExports = getEntryPointExports(newApiProgram, newApiChecker, newApiEntryPoints); + +const oldApiTypes = getTypesWithMethods(oldApiSourceFiles, visitOld); +oldApiTypes.set("ts", getNamespaceFunctions(oldApiSourceFiles, "ts")); + +const newApiTypes = getExportedTypesWithMethods(newApiExports); +newApiTypes.set("ts", [getExportedTopLevelFunctions(newApiExports, newApiChecker), new Set()]); + +const acceptedDiffs = getAcceptedDiffs(); + +const report: string[] = [ + "# This report is generated by tools/scripts/gen/apidiff.mts.", + `# Old API: TypeScript ${typescriptVersion} (node_modules/typescript/lib/typescript.d.ts)`, + "# New API: public package entry points", +]; + +const comparisons = [...typeMappings].map(([oldType, newTypes]) => { + const oldMethods = oldApiTypes.get(oldType)!; + const acceptedChanges = acceptedDiffs.get(oldType) ?? new Map(); + let missing: string[] = [...oldMethods.keys()]; + const present: string[] = []; + const newTypeArray = Array.isArray(newTypes) ? newTypes : [newTypes]; + for (const newType of newTypeArray) { + const currMissing: string[] = []; + const newMethods = newApiTypes.get(newType)!; + for (const method of missing) { + if (newMethods[0].has(method)) { + present.push(method); + newMethods[0].delete(method); + newMethods[1].add(method); + } + else if (newMethods[1].has(method)) { + present.push(method); + } + else if (acceptedChanges.has(method)) { + present.push(method); + const [newType, newMethodName] = acceptedChanges.get(method)!.split("."); + const actualNewType = newApiTypes.get(newType); + if (actualNewType) { + actualNewType[0].delete(newMethodName); + actualNewType[1].add(method); + } + } + else { + currMissing.push(method); + } + } + missing = currMissing; + } + return { + oldType, + newTypes, + present: present.sort(), + missing: missing.sort(), + }; +}); + +report.push( + `Types not compared:`, +); +for (const [type, _] of oldApiTypes) { + typeMappings.has(type) || report.push(`- ${type}`); +} +report.push( + "", +); + +for (const comparison of comparisons) { + const { oldType, newTypes, present, missing } = comparison; + const newType = Array.isArray(newTypes) ? newTypes.join(", ") : newTypes; + report.push( + "", + `# ${oldType} (old) methods compared to ${newType} (new).`, + `## (${present.length}) ${oldType} methods matched in async ${newType} ##`, + "", + `## ${oldType} methods missing from async ${newType} (${missing.length}) ##`, + ...missing, + "", + ); +} + +report.push("\n\n # New Methods in async API (temporarily reported for increased ease of matching)"); + +for (const [newType, newMethods] of newApiTypes) { + report.push( + `## New ${newType} methods in async API (${newMethods[0].size}) ##`, + ...newMethods[0], + "", + ); +} + +fs.writeFileSync(outputPath, report.join("\n")); + +function createSourceFile(file: string): ts.SourceFile { + return ts.createSourceFile( + file, + fs.readFileSync(file, "utf8"), + ts.ScriptTarget.Latest, + true, + ); +} + +function createNewApiProgram(): ts.Program { + const configPath = path.join(newApiPackageDirectory, "tsconfig.json"); + const configFile = ts.readConfigFile(configPath, ts.sys.readFile); + if (configFile.error) { + throw new Error(ts.flattenDiagnosticMessageText(configFile.error.messageText, "\n")); + } + const config = ts.parseJsonConfigFileContent(configFile.config, ts.sys, newApiPackageDirectory, { noEmit: true }, configPath); + if (config.errors.length > 0) { + throw new Error(config.errors.map(error => ts.flattenDiagnosticMessageText(error.messageText, "\n")).join("\n")); + } + return ts.createProgram({ + rootNames: config.fileNames, + options: config.options, + projectReferences: config.projectReferences, + }); +} + +type EntryPointExports = ReadonlyMap>; + +function getEntryPointExports(program: ts.Program, checker: ts.TypeChecker, entryPoints: readonly string[]): EntryPointExports { + const exports = new Map>(); + for (const entryPoint of entryPoints) { + const sourceFile = program.getSourceFile(entryPoint); + if (!sourceFile) throw new Error(`Could not find API entry point ${entryPoint}`); + const moduleSymbol = checker.getSymbolAtLocation(sourceFile); + if (!moduleSymbol) throw new Error(`Could not resolve API entry point ${entryPoint}`); + for (const exportedSymbol of checker.getExportsOfModule(moduleSymbol)) { + const symbols = exports.get(exportedSymbol.name) ?? new Set(); + symbols.add(resolveAlias(exportedSymbol, checker)); + exports.set(exportedSymbol.name, symbols); + } + } + return exports; +} + +function resolveAlias(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol { + return symbol.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol; +} + +function getTypesWithMethods(sourceFiles: readonly ts.SourceFile[], visitNode: (node: ts.Node, types: Map) => void): Map { + const types = new Map(); + for (const sourceFile of sourceFiles) { + visit(sourceFile); + } + return types; + + function visit(node: ts.Node): void { + visitNode(node, types); + ts.forEachChild(node, visit); + } +} + +function getAcceptedDiffs(): Map> { + const diffs = new Map>(); + const contents = fs.readFileSync(path.join(repoRoot, "tsc", "testdata", "apiAccepted.txt"), "utf-8").split("\n"); + contents.slice(2).forEach(line => { + const [oldMethod, newMethod, _] = line.split("|"); + const [oldType, oldMethodName] = oldMethod.split("."); + if (!diffs.has(oldType)) diffs.set(oldType, new Map()); + diffs.get(oldType)!.set(oldMethodName, newMethod); + }); + return diffs; +} + +function visitOld(node: ts.Node, types: Map>): void { + if ((ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.name) { + const methods = types.get(node.name.text) ?? new Set(); + for (const member of node.members) { + if ( + (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) + && !hasModifier(member, ts.SyntaxKind.PrivateKeyword) + && !hasModifier(member, ts.SyntaxKind.ProtectedKeyword) + ) { + const name = getPropertyName(member.name); + if (name !== undefined) methods.add(name); + } + } + if (methods.size > 0) types.set(node.name.text, methods); + } +} + +function getExportedTypesWithMethods(exports: EntryPointExports): Map, seen: Set]> { + const types = new Map, seen: Set]>(); + for (const [exportName, symbols] of exports) { + const methods = new Set(); + for (const symbol of symbols) { + for (const declaration of symbol.declarations ?? []) { + if (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) { + addPublicMethods(declaration.members, methods); + } + } + } + if (methods.size > 0) types.set(exportName, [methods, new Set()]); + } + return types; +} + +function addPublicMethods(members: ts.NodeArray, methods: Set): void { + for (const member of members) { + if ( + (ts.isMethodDeclaration(member) || ts.isMethodSignature(member)) + && !hasModifier(member, ts.SyntaxKind.PrivateKeyword) + && !hasModifier(member, ts.SyntaxKind.ProtectedKeyword) + ) { + const name = getPropertyName(member.name); + if (name !== undefined) methods.add(name); + } + } +} + +function getNamespaceFunctions(sourceFiles: readonly ts.SourceFile[], namespace: string): Set { + const functions = new Set(); + for (const sourceFile of sourceFiles) { + for (const statement of sourceFile.statements) { + if ( + ts.isModuleDeclaration(statement) + && statement.name.text === namespace + && statement.body + && ts.isModuleBlock(statement.body) + ) { + for (const member of statement.body.statements) { + if (ts.isFunctionDeclaration(member) && member.name) { + functions.add(member.name.text); + } + } + } + } + } + return functions; +} + +function getExportedTopLevelFunctions(exports: EntryPointExports, checker: ts.TypeChecker): Set { + const functions = new Set(); + for (const [exportName, symbols] of exports) { + for (const symbol of symbols) { + const declaration = symbol.valueDeclaration; + if ( + declaration + && checker.getTypeOfSymbolAtLocation(symbol, declaration).getCallSignatures().length > 0 + ) { + functions.add(exportName); + break; + } + } + } + return functions; +} + +function hasModifier(node: ts.Node, kind: ts.SyntaxKind): boolean { + return ts.canHaveModifiers(node) && ts.getModifiers(node)?.some(modifier => modifier.kind === kind) === true; +} + +function getPropertyName(name: ts.PropertyName): string | undefined { + if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) { + return name.text; + } + return undefined; +} diff --git a/tsc/testdata/apiAccepted.txt b/tsc/testdata/apiAccepted.txt index b6c233e403dee..e7dc6db242ce5 100644 --- a/tsc/testdata/apiAccepted.txt +++ b/tsc/testdata/apiAccepted.txt @@ -3,6 +3,7 @@ originalType.MethodName|newType.MethodName|reason (will be discarded in parsing) TypeChecker.tryGetMemberInModuleExports|Checker.getMemberInModuleExports|rename TypeChecker.getAugmentedPropertiesOfType|| use `Type.getApparentProperties()` instead Program.getTypeChecker|| removed +Program.getOptionsDiagnostics|| removed Project.containsFile|| same as `Program` method Project.getFileNames|| same as `Program` method Project.getRootFiles||same as `Program` method diff --git a/tsc/testdata/apiDiff.txt b/tsc/testdata/apiDiff.txt index 6663c9e07eb69..c1ab41f02ad63 100644 --- a/tsc/testdata/apiDiff.txt +++ b/tsc/testdata/apiDiff.txt @@ -99,13 +99,12 @@ getSourceFiles # Program (old) methods compared to Program (new). -## (12) Program methods matched in async Program ## +## (13) Program methods matched in async Program ## -## Program methods missing from async Program (11) ## +## Program methods missing from async Program (10) ## getIdentifierCount getInstantiationCount getNodeCount -getOptionsDiagnostics getProjectReferences getRelationCacheSizes getResolvedProjectReferences @@ -301,10 +300,10 @@ getFlags getName -# Type (old) methods compared to Type (new). -## (13) Type methods matched in async Type ## +# Type (old) methods compared to Type, ts (new). +## (14) Type methods matched in async Type, ts ## -## Type methods missing from async Type (10) ## +## Type methods missing from async Type, ts (9) ## getConstraint getDefault getFlags @@ -312,7 +311,6 @@ isClass isIntersection isLiteral isNumberLiteral -isStringLiteral isUnion isUnionOrIntersection