Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade TypeScript to 5.3.2. #1490

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"source-map-support": "^0.5.19",
"tslib": "^2.2.0",
"tslint": "^6.1.3",
"typescript": "5.2.2"
"typescript": "5.3.2"
},
"scripts": {
"build": "tsc",
Expand Down
33 changes: 22 additions & 11 deletions src/googmodule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ export interface GoogModuleProcessorHost {
* Takes the import URL of an ES6 import and returns the googmodule module
* name for the imported module, iff the module is an original closure
* JavaScript file.
*
* Warning: If this function is present, GoogModule won't produce diagnostics
* for multiple provides.
*/
jsPathToModuleName?(importPath: string): string|undefined;
jsPathToModuleName?
(importPath: string): {name: string, multipleProvides: boolean}|undefined;
/**
* Takes the import URL of an ES6 import and returns the property name that
* should be stripped from the usage.
Expand Down Expand Up @@ -89,7 +87,8 @@ export function jsPathToNamespace(
host: GoogModuleProcessorHost, context: ts.Node,
diagnostics: ts.Diagnostic[], importPath: string,
getModuleSymbol: () => ts.Symbol | undefined): string|undefined {
const namespace = localJsPathToNamespace(host, importPath);
const namespace =
localJsPathToNamespace(host, context, diagnostics, importPath);
if (namespace) return namespace;

const moduleSymbol = getModuleSymbol();
Expand All @@ -105,15 +104,21 @@ export function jsPathToNamespace(
* Forwards to `jsPathToModuleName` on the host if present.
*/
export function localJsPathToNamespace(
host: GoogModuleProcessorHost, importPath: string): string|undefined {
host: GoogModuleProcessorHost, context: ts.Node|undefined,
diagnostics: ts.Diagnostic[], 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".
return importPath.substring('goog:'.length);
}

if (host.jsPathToModuleName) {
return host.jsPathToModuleName(importPath);
const module = host.jsPathToModuleName(importPath);
if (!module) return undefined;
if (module.multipleProvides) {
reportMultipleProvidesError(context, diagnostics, importPath);
}
return module.name;
}

return undefined;
Expand Down Expand Up @@ -394,10 +399,7 @@ function getGoogNamespaceFromClutzComments(
findLocalInDeclarations(moduleSymbol, '__clutz_multiple_provides');
if (hasMultipleProvides) {
// Report an error...
reportDiagnostic(
tsickleDiagnostics, context,
`referenced JavaScript module ${
tsImport} provides multiple namespaces and cannot be imported by path.`);
reportMultipleProvidesError(context, tsickleDiagnostics, tsImport);
// ... but continue producing an emit that effectively references the first
// provided symbol (to continue finding any additional errors).
}
Expand All @@ -411,6 +413,15 @@ function getGoogNamespaceFromClutzComments(
return actualNamespace;
}

function reportMultipleProvidesError(
context: ts.Node|undefined, diagnostics: ts.Diagnostic[],
importPath: string) {
reportDiagnostic(
diagnostics, context,
`referenced JavaScript module ${
importPath} provides multiple namespaces and cannot be imported by path.`);
}

/**
* Converts a TS/ES module './import/path' into a goog.module compatible
* namespace, handling regular imports and `goog:` namespace imports.
Expand Down
7 changes: 3 additions & 4 deletions src/jsdoc_transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -846,10 +846,9 @@ export function jsdocTransformer(
continue;
}
}
const newDecl =
// TODO: go/ts50upgrade - Remove after upgrade.
// tslint:disable-next-line:no-unnecessary-type-assertion
ts.visitNode(decl, visitor, ts.isVariableDeclaration)!;
const newDecl = ts.setEmitFlags(
ts.visitNode(decl, visitor, ts.isVariableDeclaration)!,
ts.EmitFlags.NoComments);
const newStmt = ts.factory.createVariableStatement(
varStmt.modifiers,
ts.factory.createVariableDeclarationList([newDecl], flags));
Expand Down
49 changes: 44 additions & 5 deletions src/ns_transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ export function namespaceTransformer(
// transformation fails.
function transformNamespace(
ns: ts.ModuleDeclaration,
mergedDecl: ts.ClassDeclaration|
ts.InterfaceDeclaration): ts.Statement[] {
mergedDecl: ts.ClassDeclaration|ts.InterfaceDeclaration|
ts.EnumDeclaration): ts.Statement[] {
if (!ns.body || !ts.isModuleBlock(ns.body)) {
if (ts.isModuleDeclaration(ns)) {
error(
Expand All @@ -83,10 +83,15 @@ export function namespaceTransformer(
return [ns];
}
const nsName = getIdentifierText(ns.name as ts.Identifier);
const mergingWithEnum = ts.isEnumDeclaration(mergedDecl);
const transformedNsStmts: ts.Statement[] = [];
for (const stmt of ns.body.statements) {
if (ts.isEmptyStatement(stmt)) continue;
if (ts.isClassDeclaration(stmt)) {
if (mergingWithEnum) {
errorNotAllowed(stmt, 'class');
continue;
}
transformInnerDeclaration(
stmt, (classDecl, notExported, hoistedIdent) => {
return ts.factory.updateClassDeclaration(
Expand All @@ -95,12 +100,20 @@ export function namespaceTransformer(
classDecl.members);
});
} else if (ts.isEnumDeclaration(stmt)) {
if (mergingWithEnum) {
errorNotAllowed(stmt, 'enum');
continue;
}
transformInnerDeclaration(
stmt, (enumDecl, notExported, hoistedIdent) => {
return ts.factory.updateEnumDeclaration(
enumDecl, notExported, hoistedIdent, enumDecl.members);
});
} else if (ts.isInterfaceDeclaration(stmt)) {
if (mergingWithEnum) {
errorNotAllowed(stmt, 'interface');
continue;
}
transformInnerDeclaration(
stmt, (interfDecl, notExported, hoistedIdent) => {
return ts.factory.updateInterfaceDeclaration(
Expand All @@ -109,20 +122,39 @@ export function namespaceTransformer(
interfDecl.members);
});
} else if (ts.isTypeAliasDeclaration(stmt)) {
if (mergingWithEnum) {
errorNotAllowed(stmt, 'type alias');
continue;
}
transformTypeAliasDeclaration(stmt);
} else if (ts.isVariableStatement(stmt)) {
if ((ts.getCombinedNodeFlags(stmt.declarationList) &
ts.NodeFlags.Const) === 0) {
error(
stmt,
'non-const values are not supported. (go/ts-merged-namespaces)');
continue;
}
if (!ts.isInterfaceDeclaration(mergedDecl)) {
error(
stmt,
'const declaration only allowed when merging with an interface (go/ts-merged-namespaces)');
continue;
}
transformConstDeclaration(stmt);
} else if (ts.isFunctionDeclaration(stmt)) {
if (!ts.isEnumDeclaration(mergedDecl)) {
error(
stmt,
'function declaration only allowed when merging with an enum (go/ts-merged-namespaces)');
}
transformInnerDeclaration(
stmt, (funcDecl, notExported, hoistedIdent) => {
return ts.factory.updateFunctionDeclaration(
funcDecl, notExported, funcDecl.asteriskToken,
hoistedIdent, funcDecl.typeParameters,
funcDecl.parameters, funcDecl.type, funcDecl.body);
});
} else {
error(
stmt,
Expand All @@ -145,6 +177,12 @@ export function namespaceTransformer(

// Local functions follow.

function errorNotAllowed(stmt: ts.Statement, declKind: string) {
error(
stmt,
`${declKind} cannot be merged with enum declaration. (go/ts-merged-namespaces)`);
}

type DeclarationStatement = ts.Declaration&ts.DeclarationStatement;

function transformConstDeclaration(varDecl: ts.VariableStatement) {
Expand Down Expand Up @@ -365,12 +403,13 @@ export function namespaceTransformer(
}

if (!ts.isInterfaceDeclaration(mergedDecl) &&
!ts.isClassDeclaration(mergedDecl)) {
// The previous declaration is not a class or interface.
!ts.isClassDeclaration(mergedDecl) &&
!ts.isEnumDeclaration(mergedDecl)) {
// The previous declaration is not a class, enum, or interface.
transformedStmts.push(ns); // Nothing to do here.
error(
ns.name,
'merged declaration must be local class or interface. (go/ts-merged-namespaces)');
'merged declaration must be local class, enum, or interface. (go/ts-merged-namespaces)');
return;
}

Expand Down
1 change: 1 addition & 0 deletions src/summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class FileSummary {
modName: string|undefined;
autochunk = false;
enhanceable = false;
legacyNamespace = false;
moduleType = ModuleType.UNKNOWN;

private stringify(symbol: Symbol): string {
Expand Down
16 changes: 9 additions & 7 deletions src/transformer_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,28 +227,30 @@ export function reportDebugWarning(
* @param textRange pass to overrride the text range from the node with a more specific range.
*/
export function reportDiagnostic(
diagnostics: ts.Diagnostic[], node: ts.Node, messageText: string, textRange?: ts.TextRange,
category = ts.DiagnosticCategory.Error) {
diagnostics: ts.Diagnostic[], node: ts.Node|undefined, messageText: string,
textRange?: ts.TextRange, category = ts.DiagnosticCategory.Error) {
diagnostics.push(createDiagnostic(node, messageText, textRange, category));
}

function createDiagnostic(
node: ts.Node, messageText: string, textRange: ts.TextRange|undefined,
node: ts.Node|undefined, messageText: string,
textRange: ts.TextRange|undefined,
category: ts.DiagnosticCategory): ts.Diagnostic {
let start, length: number;
let start: number|undefined;
let length: number|undefined;
// getStart on a synthesized node can crash (due to not finding an associated
// source file). Make sure to use the original node.
node = ts.getOriginalNode(node);
if (textRange) {
start = textRange.pos;
length = textRange.end - textRange.pos;
} else {
} else if (node) {
// Only use getStart if node has a valid pos, as it might be synthesized.
start = node.pos >= 0 ? node.getStart() : 0;
length = node.end - node.pos;
}
return {
file: node.getSourceFile(),
file: node?.getSourceFile(),
start,
length,
messageText,
Expand Down Expand Up @@ -431,4 +433,4 @@ export function getPreviousDeclaration(
}
}
return null;
}
}
3 changes: 3 additions & 0 deletions src/ts_migration_exports_shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ class Generator {
fileSummary.addStrongRequire({type: Type.CLOSURE, name: 'goog'});
fileSummary.addStrongRequire(
{type: Type.CLOSURE, name: this.srcIds.googModuleId});
if (maybeDeclareLegacyNameCall) {
fileSummary.legacyNamespace = true;
}

fileSummary.autochunk = isAutoChunk;
fileSummary.moduleType = ModuleType.GOOG_MODULE;
Expand Down
26 changes: 9 additions & 17 deletions test/googmodule_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as googmodule from '../src/googmodule';
import {ModulesManifest} from '../src/modules_manifest';

import * as testSupport from './test_support';
import {outdent} from './test_support';

interface ResolvedNamespace {
name: string;
Expand Down Expand Up @@ -42,8 +43,14 @@ function processES5(
transformDynamicImport: 'closure',
};
if (pathToNamespaceMap) {
host.jsPathToModuleName = (importPath: string) =>
pathToNamespaceMap.get(importPath)?.name;
host.jsPathToModuleName = (importPath: string) => {
const module = pathToNamespaceMap.get(importPath);
if (!module) return undefined;
return {
name: module.name,
multipleProvides: false,
};
};
host.jsPathToStripProperty = (importPath: string) =>
pathToNamespaceMap.get(importPath)?.stripProperty;
}
Expand Down Expand Up @@ -71,21 +78,6 @@ function processES5(
return {output, manifest, rootDir};
}

/**
* Remove the first line (if empty) and unindents the all other lines by the
* amount of leading whitespace in the second line.
*/
function outdent(str: string) {
const lines = str.split('\n');
if (lines.length < 2) return str;
if (lines.shift() !== '') return str;
const indent = lines[0].match(/^ */)![0].length;
for (let i = 0; i < lines.length; i++) {
lines[i] = lines[i].substring(indent);
}
return lines.join('\n');
}

describe('convertCommonJsToGoogModule', () => {
beforeEach(() => {
testSupport.addDiffMatchers();
Expand Down
15 changes: 15 additions & 0 deletions test/test_support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,18 @@ export function pathToModuleName(
if (fileName === tslibPath()) return 'tslib';
return cliSupport.pathToModuleName(rootModulePath, context, fileName);
}

/**
* Remove the first line (if empty) and unindents the all other lines by the
* amount of leading whitespace in the second line.
*/
export function outdent(str: string) {
const lines = str.split('\n');
if (lines.length < 2) return str;
if (lines.shift() !== '') return str;
const indent = lines[0].match(/^ */)![0].length;
for (let i = 0; i < lines.length; i++) {
lines[i] = lines[i].substring(indent);
}
return lines.join('\n');
}
Loading
Loading