Skip to content

Commit

Permalink
Generate JsTrimmer summaries.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 574242891
  • Loading branch information
tsjs-language-eng authored and copybara-github committed Oct 17, 2023
1 parent 8b9daeb commit 0d47bd4
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 12 deletions.
1 change: 1 addition & 0 deletions demo/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export function toClosureJS(
externs: {},
emitSkipped: true,
emittedFiles: [],
fileSummaries: new Map(),
};
}
return tsickle.emit(program, transformerHost, writeFile);
Expand Down
22 changes: 18 additions & 4 deletions src/googmodule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ export function jsPathToNamespace(
host: GoogModuleProcessorHost, context: ts.Node,
diagnostics: ts.Diagnostic[], importPath: string,
getModuleSymbol: () => ts.Symbol | undefined): string|undefined {
const namespace = localJsPathToNamespace(host, importPath);
if (namespace) return namespace;

const moduleSymbol = getModuleSymbol();
if (!moduleSymbol) return;
return getGoogNamespaceFromClutzComments(
context, diagnostics, importPath, moduleSymbol);
}

/**
* Resolves an import path to its goog namespace, if it points to an original
* closure JavaScript file, using only local information.
*
* Forwards to `jsPathToModuleName` on the host if present.
*/
export function localJsPathToNamespace(
host: GoogModuleProcessorHost, importPath: string): string|undefined {
if (importPath.match(/^goog:/)) {
// This is a namespace import, of the form "goog:foo.bar".
// Fix it to just "foo.bar".
Expand All @@ -99,10 +116,7 @@ export function jsPathToNamespace(
return host.jsPathToModuleName(importPath);
}

const moduleSymbol = getModuleSymbol();
if (!moduleSymbol) return;
return getGoogNamespaceFromClutzComments(
context, diagnostics, importPath, moduleSymbol);
return undefined;
}

/**
Expand Down
5 changes: 5 additions & 0 deletions src/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ export function relative(base: string, rel: string): string {
export function normalize(path: string): string {
return ts.resolvePath(path);
}

/** Wrapper around ts.resolvePath. */
export function resolve(path: string, ...paths: string[]): string {
return ts.resolvePath(path, ...paths);
}
125 changes: 125 additions & 0 deletions src/summary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

/** The Type of an import, as used in JsTrimmer. */
export enum Type {
UNKNOWN = 0,
/** The symbol type for Closure namespace. */
CLOSURE,
/** The symbol type for a GSS namespace. */
GSS,
/** The symbol type for a Soy namespace. */
SOY,
/** The symbol type for an extensionless google3-relative CSS/GSS path. */
CSSPATH,
/** The symbol type for a google3-relative ES module path. */
ESPATH,
}

/** The module system used by a file. */
export enum ModuleType {
UNKNOWN = 0,
GOOG_PROVIDE,
GOOG_MODULE,
ES_MODULE,
}

/** A single imported symbol. */
export interface Symbol {
type: Type;
name: string;
}

/**
* The JsTrimmer file summary for a single file. Contains imported and
* exported symbols, as well as some other information required for sorting and
* pruning files.
*/
export class FileSummary {
// These sets are implemented as Maps of jsonified Symbol to Symbol because
// JavaScript Sets use object address, not object contents. Similarly, we use
// getters and setters for these to hide this implementation detail.
private readonly provideSet = new Map<string, Symbol>();
private readonly strongRequireSet = new Map<string, Symbol>();
private readonly weakRequireSet = new Map<string, Symbol>();
private readonly dynamicRequireSet = new Map<string, Symbol>();
private readonly modSet = new Map<string, Symbol>();
private readonly enhancedSet = new Map<string, Symbol>();
toggles: string[] = [];
modName: string|undefined;
autochunk = false;
enhanceable = false;
moduleType = ModuleType.UNKNOWN;

private stringify(symbol: Symbol): string {
return JSON.stringify(symbol);
}

addProvide(provide: Symbol) {
this.provideSet.set(this.stringify(provide), provide);
}

get provides(): Symbol[] {
return [...this.provideSet.values()];
}

addStrongRequire(strongRequire: Symbol) {
this.strongRequireSet.set(this.stringify(strongRequire), strongRequire);
}

get strongRequires(): Symbol[] {
return [...this.strongRequireSet.values()];
}

addWeakRequire(weakRequire: Symbol) {
this.weakRequireSet.set(this.stringify(weakRequire), weakRequire);
}

get weakRequires(): Symbol[] {
return [...this.weakRequireSet.values()];
}

addDynamicRequire(dynamicRequire: Symbol) {
this.dynamicRequireSet.set(this.stringify(dynamicRequire), dynamicRequire);
}

get dynamicRequires(): Symbol[] {
return [...this.dynamicRequireSet.values()];
}

addMods(mods: Symbol) {
this.modSet.set(this.stringify(mods), mods);
}

get mods(): Symbol[] {
return [...this.modSet.values()];
}

addEnhanced(enhanced: Symbol) {
this.enhancedSet.set(this.stringify(enhanced), enhanced);
}

get enhanced(): Symbol[] {
return [...this.enhancedSet.values()];
}
}

/** Provides dependencies for file generation. */
export interface SummaryGenerationProcessorHost {
/** @deprecated use unknownTypesPaths instead */
typeBlackListPaths?: Set<string>;
/** If provided, a set of paths whose types should always generate as {?}. */
unknownTypesPaths?: Set<string>;
/** See compiler_host.ts */
rootDirsRelative(fileName: string): string;
/**
* Whether to convert CommonJS require() imports to goog.module() and
* goog.require() calls.
*/
googmodule: boolean;
}
31 changes: 25 additions & 6 deletions src/ts_migration_exports_shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import * as ts from 'typescript';

import {ModulesManifest} from './modules_manifest';
import {FileSummary, ModuleType, Type} from './summary';
import {getGoogFunctionName, isAnyTsmesCall, isGoogCallExpressionOf, isTsmesDeclareLegacyNamespaceCall, isTsmesShorthandCall, reportDiagnostic} from './transformer_util';

/** Provides dependencies for file generation. */
Expand Down Expand Up @@ -46,7 +47,8 @@ export type TsMigrationExportsShimFileMap = Map<string, string>;
export function createTsMigrationExportsShimTransformerFactory(
typeChecker: ts.TypeChecker, host: TsMigrationExportsShimProcessorHost,
manifest: ModulesManifest, tsickleDiagnostics: ts.Diagnostic[],
outputFileMap: TsMigrationExportsShimFileMap):
outputFileMap: TsMigrationExportsShimFileMap,
fileSummaries: Map<string, FileSummary>):
ts.TransformerFactory<ts.SourceFile> {
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
return (src: ts.SourceFile): ts.SourceFile => {
Expand All @@ -70,13 +72,17 @@ export function createTsMigrationExportsShimTransformerFactory(
// TODO(martinprobst): the empty files might cause issues with code
// that should be in mods or modules.
outputFileMap.set(tsmesFile, '');
const fileSummary = new FileSummary();
fileSummary.moduleType = ModuleType.UNKNOWN;
fileSummaries.set(tsmesFile, fileSummary);
if (context.getCompilerOptions().declaration) {
outputFileMap.set(dtsFile, '');
}
return src;
}
const result = generator.generateExportShimJavaScript();
outputFileMap.set(tsmesFile, result);
const [content, fileSummary] = generator.generateExportShimJavaScript();
outputFileMap.set(tsmesFile, content);
fileSummaries.set(tsmesFile, fileSummary);
if (context.getCompilerOptions().declaration) {
const dtsResult = generator.generateExportShimDeclarations();
outputFileMap.set(dtsFile, dtsResult);
Expand Down Expand Up @@ -396,7 +402,7 @@ class Generator {
*
* NOTE: This code must be written to be compatible as-is with IE11.
*/
generateExportShimJavaScript(): string {
generateExportShimJavaScript(): [string, FileSummary] {
if (!this.outputIds || !this.tsmesBreakdown) {
throw new Error('tsmes call must be extracted first');
}
Expand Down Expand Up @@ -427,11 +433,12 @@ class Generator {
this.manifest.addReferencedModule(
this.outputIds.google3Path, this.srcIds.googModuleId);

const pintoModuleAnnotation = containsAtPintoModule(this.src) ?
const isAutoChunk = containsAtPintoModule(this.src);
const pintoModuleAnnotation = isAutoChunk ?
'@pintomodule found in original_file' :
'pintomodule absent in original_file';

return lines(
const content = lines(
'/**',
' * @fileoverview generator:ts_migration_exports_shim.ts',
' * original_file:' + this.srcIds.google3Path,
Expand All @@ -443,6 +450,18 @@ class Generator {
exportsAssignment,
'',
);

const fileSummary = new FileSummary();
fileSummary.addProvide(
{type: Type.CLOSURE, name: this.outputIds.googModuleId});
fileSummary.addStrongRequire({type: Type.CLOSURE, name: 'goog'});
fileSummary.addStrongRequire(
{type: Type.CLOSURE, name: this.srcIds.googModuleId});

fileSummary.autochunk = isAutoChunk;
fileSummary.moduleType = ModuleType.GOOG_MODULE;

return [content, fileSummary];
}

/**
Expand Down
22 changes: 20 additions & 2 deletions src/tsickle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as googmodule from './googmodule';
import {jsdocTransformer, removeTypeAssertions} from './jsdoc_transformer';
import {ModulesManifest} from './modules_manifest';
import {namespaceTransformer} from './ns_transformer';
import {FileSummary, SummaryGenerationProcessorHost} from './summary';
import {isDtsFileName} from './transformer_util';
import * as tsmes from './ts_migration_exports_shim';
import {makeTsickleDeclarationMarkerTransformerFactory} from './tsickle_declaration_marker';
Expand All @@ -29,10 +30,12 @@ export {pathToModuleName} from './cli_support';
// Retained here for API compatibility.
export {getGeneratedExterns} from './externs';
export {FileMap, ModulesManifest} from './modules_manifest';
export {FileSummary, ModuleType, Symbol, Type} from './summary';

export interface TsickleHost extends googmodule.GoogModuleProcessorHost,
tsmes.TsMigrationExportsShimProcessorHost,
AnnotatorHost {
AnnotatorHost,
SummaryGenerationProcessorHost {
/**
* Whether to downlevel decorators
*/
Expand Down Expand Up @@ -79,6 +82,11 @@ export interface TsickleHost extends googmodule.GoogModuleProcessorHost,
* Whether to add suppressions by default.
*/
generateExtraSuppressions: boolean;

/**
* Whether to generate summaries.
*/
generateSummary?: boolean;
}


Expand All @@ -90,6 +98,7 @@ export function mergeEmitResults(emitResults: EmitResult[]): EmitResult {
{[fileName: string]: {output: string, moduleNamespace: string}} = {};
const modulesManifest = new ModulesManifest();
const tsMigrationExportsShimFiles = new Map<string, string>();
const fileSummaries = new Map<string, FileSummary>();
for (const er of emitResults) {
diagnostics.push(...er.diagnostics);
emitSkipped = emitSkipped || er.emitSkipped;
Expand All @@ -101,6 +110,9 @@ export function mergeEmitResults(emitResults: EmitResult[]): EmitResult {
for (const [k, v] of er.tsMigrationExportsShimFiles) {
tsMigrationExportsShimFiles.set(k, v);
}
for (const [k, v] of er.fileSummaries) {
fileSummaries.set(k, v);
}
}

return {
Expand All @@ -110,6 +122,7 @@ export function mergeEmitResults(emitResults: EmitResult[]): EmitResult {
externs,
tsMigrationExportsShimFiles,
modulesManifest,
fileSummaries,
};
}

Expand All @@ -127,6 +140,8 @@ export interface EmitResult extends ts.EmitResult {
* Filenames are google3 relative.
*/
tsMigrationExportsShimFiles: tsmes.TsMigrationExportsShimFileMap;

fileSummaries: Map<string, FileSummary>;
}

export interface EmitTransformers {
Expand Down Expand Up @@ -182,17 +197,19 @@ export function emit(
modulesManifest: new ModulesManifest(),
externs: {},
tsMigrationExportsShimFiles: new Map(),
fileSummaries: new Map(),
};
}

const modulesManifest = new ModulesManifest();
const tsMigrationExportsShimFiles = new Map<string, string>();
const tsickleSourceTransformers: Array<ts.TransformerFactory<ts.SourceFile>> =
[];
const fileSummaries = new Map<string, FileSummary>();
tsickleSourceTransformers.push(
tsmes.createTsMigrationExportsShimTransformerFactory(
typeChecker, host, modulesManifest, tsickleDiagnostics,
tsMigrationExportsShimFiles));
tsMigrationExportsShimFiles, fileSummaries));

if (host.transformTypesToClosure) {
// Only add @suppress {checkTypes} comments when also adding type
Expand Down Expand Up @@ -282,6 +299,7 @@ export function emit(
diagnostics: [...tsDiagnostics, ...tsickleDiagnostics],
externs,
tsMigrationExportsShimFiles,
fileSummaries,
};
}

Expand Down

0 comments on commit 0d47bd4

Please sign in to comment.