Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(596)

Unified Diff: lib/main.ts

Issue 2394683003: JS Interop Facade generation polish.
Patch Set: more cleanup Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/facade_converter.ts ('k') | lib/merge.ts » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/main.ts
diff --git a/lib/main.ts b/lib/main.ts
index 7c3c0d6d4579597d8f5d48e93a3c074be3dbdb45..afc616b33cf94e4b91aeec76ea0aa46b62804815 100644
--- a/lib/main.ts
+++ b/lib/main.ts
@@ -1,17 +1,16 @@
+import * as dartStyle from 'dart-style';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import * as base from './base';
import {Set, TranspilerBase} from './base';
-
-import mkdirP from './mkdirp';
import DeclarationTranspiler from './declaration';
+import {FacadeConverter, NameRewriter} from './facade_converter';
import * as merge from './merge';
+import mkdirP from './mkdirp';
import ModuleTranspiler from './module';
import TypeTranspiler from './type';
-import {FacadeConverter, NameRewriter} from './facade_converter';
-import * as dartStyle from 'dart-style';
export interface TranspilerOptions {
/**
@@ -19,18 +18,18 @@ export interface TranspilerOptions {
* directly to the offending line.
*/
failFast?: boolean;
- /** Whether to generate 'library a.b.c;' names from relative file paths. */
- generateLibraryName?: boolean;
+ /**
+ * Pass in a module name (e.g.) d3 instead of determining the module name fro the d.ts files.
+ * This is useful when using libraries that assume they will be loaded with a JS module loader
+ * without having to use a JS module loader.
+ */
+ moduleName?: string;
/**
* A base path to relativize absolute file paths against. This is useful for library name
* generation (see above) and nicer file names in error messages.
*/
basePath?: string;
/**
- * Use dart:html instead of the raw JavaScript DOM when generated Dart code.
- */
- useHtml?: boolean;
- /**
* Enforce conventions of public/private keyword and underscore prefix
*/
enforceUnderscoreConventions?: boolean;
@@ -82,15 +81,16 @@ export class Transpiler {
private declarationTranspiler: DeclarationTranspiler;
private fc: FacadeConverter;
private nameRewriter: NameRewriter;
+ private typeArgumentDepth = 0;
constructor(private options: TranspilerOptions = {}) {
this.nameRewriter = new NameRewriter();
- this.fc = new FacadeConverter(this, options.typingsRoot, this.nameRewriter, options.useHtml);
+ this.fc = new FacadeConverter(this, options.typingsRoot, this.nameRewriter);
this.declarationTranspiler = new DeclarationTranspiler(
this, this.fc, options.enforceUnderscoreConventions, options.promoteFunctionLikeMembers);
this.transpilers = [
+ new ModuleTranspiler(this, this.fc, options.moduleName),
this.declarationTranspiler,
- new ModuleTranspiler(this, this.fc, options.generateLibraryName),
new TypeTranspiler(this, this.fc),
];
}
@@ -106,11 +106,6 @@ export class Transpiler {
}
fileNames = fileNames.map((f) => this.normalizeSlashes(f));
let host = this.createCompilerHost();
- if (this.options.basePath && destination === undefined) {
- throw new Error(
- 'Must have a destination path when a basePath is specified ' + this.options.basePath);
- }
- let destinationRoot = destination || this.options.basePath || '';
let program = ts.createProgram(fileNames, this.getCompilerOptions(), host);
this.fc.setTypeChecker(program.getTypeChecker());
this.declarationTranspiler.setTypeChecker(program.getTypeChecker());
@@ -122,11 +117,47 @@ export class Transpiler {
this.errors = [];
+ let sourceFileMap: {[s: string]: ts.SourceFile} = {};
+ sourceFiles.forEach((f: ts.SourceFile) => { sourceFileMap[f.fileName] = f; });
+
+ // Check for global module export declarations and propogate them to
+ // and propogate
+ sourceFiles.forEach((f: ts.SourceFile) => {
+ f.statements.forEach((n: ts.Node) => {
+ if (n.kind !== ts.SyntaxKind.GlobalModuleExportDeclaration) return;
+ // This is the name we are interested in for Dart purposes until Dart supports AMD module
+ // loaders. This module name should all be reflected by all modules exported by this
+ // library as we need to specify a global module location for every Dart library.
+ let globalModuleName = base.ident((n as ts.GlobalModuleExportDeclaration).name);
+ f.moduleName = globalModuleName;
+
+ f.statements.forEach((e: ts.Node) => {
+ if (e.kind !== ts.SyntaxKind.ExportDeclaration) return;
+ let exportDecl = e as ts.ExportDeclaration;
+ if (!exportDecl.moduleSpecifier) return;
+ let moduleLocation = <ts.StringLiteral>exportDecl.moduleSpecifier;
+ let location = moduleLocation.text;
+ let resolvedPath = host.resolveModuleNames([location], f.fileName);
+ resolvedPath.forEach((p) => {
+ if (p.isExternalLibraryImport) return;
+ let exportedFile = sourceFileMap[p.resolvedFileName];
+ exportedFile.moduleName = globalModuleName;
+ });
+ });
+ });
+ });
+
sourceFiles.forEach((f: ts.SourceFile) => {
let dartCode = this.translate(f);
- let outputFile = this.getOutputPath(path.resolve(f.fileName), destinationRoot);
- mkdirP(path.dirname(outputFile));
- fs.writeFileSync(outputFile, dartCode);
+
+ if (destination) {
+ let outputFile = this.getOutputPath(path.resolve(f.fileName), destination);
+ console.log('Output file:', outputFile);
+ mkdirP(path.dirname(outputFile));
+ fs.writeFileSync(outputFile, dartCode);
+ } else {
+ console.log(dartCode);
+ }
});
this.checkForErrors(program);
}
@@ -181,9 +212,8 @@ export class Transpiler {
// Visible for testing.
getOutputPath(filePath: string, destinationRoot: string): string {
- let relative = this.getRelativeFileName(filePath);
- let dartFile = relative.replace(/.(js|es6|d\.ts|ts)$/, '.dart');
- return this.normalizeSlashes(path.join(destinationRoot, dartFile));
+ let relative = this.getDartFileName(filePath);
+ return this.normalizeSlashes(path.join(destinationRoot, relative));
}
public pushContext(context: OutputContext) { this.outputStack.push(this.outputs[context]); }
@@ -205,7 +235,7 @@ export class Transpiler {
}
this.lastCommentIdx = -1;
- merge.normalizeSourceFile(sourceFile);
+ merge.normalizeSourceFile(sourceFile, this.fc);
this.pushContext(OutputContext.Default);
this.visit(sourceFile);
this.popContext();
@@ -267,9 +297,9 @@ export class Transpiler {
* Returns `filePath`, relativized to the program's `basePath`.
* @param filePath Optional path to relativize, defaults to the current file's path.
*/
- getRelativeFileName(filePath?: string) {
+ getRelativeFileName(filePath?: string): string {
if (filePath === undefined) filePath = path.resolve(this.currentFile.fileName);
- // TODO(martinprobst): Use path.isAbsolute on node v0.12.
+ // TODO(jacobr): Use path.isAbsolute on node v0.12.
if (this.normalizeSlashes(path.resolve('/x/', filePath)) !== filePath) {
return filePath; // already relative.
}
@@ -280,6 +310,21 @@ export class Transpiler {
return this.normalizeSlashes(path.relative(base, filePath));
}
+ getDartFileName(filePath?: string): string {
+ if (filePath === undefined) filePath = path.resolve(this.currentFile.fileName);
+ filePath = this.normalizeSlashes(filePath);
+ filePath = filePath.replace(/\.(js|es6|d\.ts|ts)$/, '.dart');
+ // Normalize from node module file path pattern to
+ filePath = filePath.replace(/([^/]+)\/index.dart$/, '$1.dart');
+ return this.getRelativeFileName(filePath);
+ }
+
+ isJsModuleFile(): boolean {
+ // Treat files as being part of js modules if they match the node module file location
+ // convention of module_name/index.js.
+ return !('/' + this.currentFile.fileName).match(/\/index\.(js|es6|d\.ts|ts)$/);
+ }
+
private get currentOutput(): Output { return this.outputStack[this.outputStack.length - 1]; }
emit(s: string) { this.currentOutput.emit(s); }
@@ -287,6 +332,11 @@ export class Transpiler {
maybeLineBreak() { return this.currentOutput.maybeLineBreak(); }
enterCodeComment() { return this.currentOutput.enterCodeComment(); }
exitCodeComment() { return this.currentOutput.exitCodeComment(); }
+
+ enterTypeArgument() { this.typeArgumentDepth++; }
+ exitTypeArgument() { this.typeArgumentDepth--; }
+ get insideTypeArgument(): boolean { return this.typeArgumentDepth > 0; }
+
emitType(s: string, comment: string) { return this.currentOutput.emitType(s, comment); }
get insideCodeComment() { return this.currentOutput.insideCodeComment; }
@@ -411,9 +461,9 @@ class Output {
}
emit(str: string) {
- if (this.result.length > 0) {
- let buffer = this.insideCodeComment ? this.codeCommentResult : this.result;
- let lastChar = buffer[buffer.length - 1];
+ let buffer = this.insideCodeComment ? this.codeCommentResult : this.result;
+ if (buffer.length > 0) {
+ let lastChar = buffer.slice(-1);
if (lastChar !== ' ' && lastChar !== '(' && lastChar !== '<' && lastChar !== '[') {
// Avoid emitting a space in obvious cases where a space is not required
// to make the output slightly prettier in cases where the DartFormatter
@@ -432,7 +482,7 @@ class Output {
return;
}
this.result += str;
- this.firstColumn = str[str.length - 1] === '\n';
+ this.firstColumn = str.slice(-1) === '\n';
}
enterCodeComment() {
« no previous file with comments | « lib/facade_converter.ts ('k') | lib/merge.ts » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698