Commit c1c9f965 authored by Tim van der Lippe's avatar Tim van der Lippe Committed by Commit Bot

Copy individual symbols and comments for Closure

Closure was unhappy with the `Object.assign` solution. Instead, use
individual assignments and add the relevant comments, so that Closure
can understand what is going on.

Sample output:

```
/*Legacy exported object*/
self.UI = self.UI || {};

/*Legacy exported object*/
UI = UI || {};

//TODO(http://crbug.com/1006759): Add type information if necessary
UI.TextEditor = TextEditor;

//TODO(http://crbug.com/1006759): Add type information if necessary
UI.TextEditor.prototype = prototype;

/** @enum {symbol} */
UI.TextEditor.Events = Events;
```

Bug: 1006759
Change-Id: Ib0e571cc027f544b316a3e3ccf8c3d606273d887
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1819248Reviewed-by: default avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Auto-Submit: Tim Van der Lippe <tvanderlippe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#698878}
parent a1143612
...@@ -6,7 +6,7 @@ import { parse, print, types } from 'recast'; ...@@ -6,7 +6,7 @@ import { parse, print, types } from 'recast';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { promisify } from 'util'; import { promisify } from 'util';
import { IdentifierKind, MemberExpressionKind, ExpressionKind } from 'ast-types/gen/kinds'; import { IdentifierKind, MemberExpressionKind, ExpressionKind, CommentKind } from 'ast-types/gen/kinds';
const readFile = promisify(fs.readFile); const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile); const writeFile = promisify(fs.writeFile);
...@@ -40,8 +40,7 @@ function getTopLevelMemberExpression(expression: MemberExpressionKind): any { ...@@ -40,8 +40,7 @@ function getTopLevelMemberExpression(expression: MemberExpressionKind): any {
} }
function rewriteSource(source: string, refactoringNamespace: string, refactoringFileName: string) { function rewriteSource(source: string, refactoringNamespace: string, refactoringFileName: string) {
const exportedMembers: IdentifierKind[] = []; const exportedMembers: {prop: IdentifierKind, comments: CommentKind[]}[] = [];
let needToObjectAssign = false;
const ast = parse(source); const ast = parse(source);
ast.program.body = ast.program.body.map((expression: any) => { ast.program.body = ast.program.body.map((expression: any) => {
...@@ -68,23 +67,19 @@ function rewriteSource(source: string, refactoringNamespace: string, refactoring ...@@ -68,23 +67,19 @@ function rewriteSource(source: string, refactoringNamespace: string, refactoring
declarationStatement.comments = expression.comments; declarationStatement.comments = expression.comments;
if (needToObjectAssign) {
console.error(`Multiple exports with the same name is invalid!`);
}
// Since there is a default export (E.g. UI.ARIAUtils and UI.ARIAUtils.Foo), we need to assign Foo to UI.ARIAUtils to make sure that reference keeps on working
needToObjectAssign = true;
return declarationStatement; return declarationStatement;
} }
console.error(`Nested field "${assignment.left.property.name}" detected! Requires manual changes.`); console.error(`Nested field "${assignment.left.property.name}" detected! Requires manual changes.`);
expression.comments = expression.comments || [];
expression.comments.push(b.commentLine(' TODO(http://crbug.com/1006759): Fix exported symbol'));
return expression; return expression;
} }
const propertyName = assignment.left.property; const propertyName = assignment.left.property;
const {object, property} = topLevelAssignment; const {object, property} = topLevelAssignment;
if (object.type === 'Identifier' && property.type === 'Identifier') { if (object.type === 'Identifier' && property.type === 'Identifier') {
// UI // UI
const namespace = object.name; const namespace = object.name;
...@@ -95,7 +90,7 @@ function rewriteSource(source: string, refactoringNamespace: string, refactoring ...@@ -95,7 +90,7 @@ function rewriteSource(source: string, refactoringNamespace: string, refactoring
const declaration = createReplacementDeclaration(propertyName, assignment.right); const declaration = createReplacementDeclaration(propertyName, assignment.right);
if (declaration) { if (declaration) {
exportedMembers.push(propertyName); exportedMembers.push({prop: propertyName, comments: expression.comments || [b.commentLine(' TODO(http://crbug.com/1006759): Add type information if necessary')]});
declaration.comments = expression.comments; declaration.comments = expression.comments;
return declaration; return declaration;
} }
...@@ -109,20 +104,40 @@ function rewriteSource(source: string, refactoringNamespace: string, refactoring ...@@ -109,20 +104,40 @@ function rewriteSource(source: string, refactoringNamespace: string, refactoring
}); });
// self.UI = self.UI || {}; // self.UI = self.UI || {};
const legacyNamespaceName = b.memberExpression(b.identifier('self'), b.identifier(refactoringNamespace), false); {
const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([])); const legacyNamespaceName = b.memberExpression(b.identifier('self'), b.identifier(refactoringNamespace), false);
ast.program.body.push(b.expressionStatement.from({expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), comments: [b.commentBlock('Legacy exported object', true, false)]})); const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([]));
ast.program.body.push(b.expressionStatement.from({expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), comments: [b.commentBlock('Legacy exported object', true, false)]}));
// self.UI.ARIAUtils = {properties}; }
const legacyNamespaceExport = b.memberExpression(b.identifier('self'), b.memberExpression(b.identifier(refactoringNamespace), b.identifier(refactoringFileName), false), false);
let exportedObjectProperties: ExpressionKind = b.objectExpression(exportedMembers.map(prop => b.objectProperty.from({key: prop, value: prop, shorthand: true })));
if (needToObjectAssign) { // UI = UI || {};
// self.UI.ARIAUtils = Object.assign(ARIAUtils, {properties}) const legacyNamespaceName = b.identifier(refactoringNamespace)
exportedObjectProperties = b.callExpression(b.memberExpression(b.identifier('Object'), b.identifier('assign'), false), [b.identifier(refactoringFileName), exportedObjectProperties]); {
const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([]));
ast.program.body.push(b.expressionStatement.from({expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), comments: [b.commentBlock('Legacy exported object', true, false)]}));
} }
ast.program.body.push(b.expressionStatement(b.assignmentExpression('=', legacyNamespaceExport, exportedObjectProperties))); // UI.ARIAUtils = ARIAUtils;
const legacyNamespaceExport = b.memberExpression(b.identifier(refactoringNamespace), b.identifier(refactoringFileName), false);
ast.program.body.push(b.expressionStatement(b.assignmentExpression.from({
operator: '=',
left: legacyNamespaceExport,
right: b.identifier(refactoringFileName),
comments: [b.commentLine(' TODO(http://crbug.com/1006759): Add type information if necessary')]
})));
// UI.ARIAUtils.Foo = Foo;
exportedMembers.forEach(({prop, comments}) => {
const legacyExportedProperty = b.memberExpression(legacyNamespaceExport, b.identifier(prop.name), false);
ast.program.body.push(b.expressionStatement(b.assignmentExpression.from({
operator: '=',
left: legacyExportedProperty,
right: b.identifier(prop.name),
comments,
})));
});
return print(ast).code; return print(ast).code;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment