From 7141c15e65583851696c22504b8aa3034cd24715 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 2 Jun 2015 17:32:03 -0700 Subject: [PATCH] fix(docs): Working generated angular2.d.ts This requires some hacks, documented in https://docs.google.com/document/d/1nNebWTiLzz5ePcit_bjZPtaiSIFU4EsQKUlX7LX0c0A/edit Changes: - include subtyping info in angular2.d.ts by adding 'extends supertype' - export missing symbols needed transitively by angular2/angular2 - because of decorator/annotation mismatch, we can't export these to applications. So I've added a separate angular2.api.ts file to re-export specifically to .d.ts generation. - Hack to remove aliases introduced by 'import * as alias' syntax - Hack to deal with Error still an interface note that we require users to install the transitive dependencies - this is how TSD works. --- .../processors/createTypeDefinitionFile.js | 5 +- .../processors/readTypeScriptModules.js | 57 ++++++++++++++++--- .../templates/type-definition.template.html | 25 +++++++- modules/angular2/angular2.api.dart | 3 + modules/angular2/angular2.api.ts | 28 +++++++++ 5 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 modules/angular2/angular2.api.dart create mode 100644 modules/angular2/angular2.api.ts diff --git a/docs/dgeni-package/processors/createTypeDefinitionFile.js b/docs/dgeni-package/processors/createTypeDefinitionFile.js index 066ebd9110..797f5925fa 100644 --- a/docs/dgeni-package/processors/createTypeDefinitionFile.js +++ b/docs/dgeni-package/processors/createTypeDefinitionFile.js @@ -15,8 +15,9 @@ module.exports = function createTypeDefinitionFile() { }; _.forEach(docs, function(doc) { // The shape of the public API is determined by what is reexported into - // angular2/angular2. - if (doc.id === 'angular2/angular2') { + // angular2/angular2, with hacks layered into angular2.api.ts + if (doc.id === 'angular2/angular2.api') { + doc.id = 'angular2/angular2'; typeDefDoc.modules.push(doc); } }); diff --git a/docs/dgeni-package/processors/readTypeScriptModules.js b/docs/dgeni-package/processors/readTypeScriptModules.js index 303bb239d7..4c2fb53586 100644 --- a/docs/dgeni-package/processors/readTypeScriptModules.js +++ b/docs/dgeni-package/processors/readTypeScriptModules.js @@ -3,7 +3,8 @@ var path = require('canonical-path'); var _ = require('lodash'); var ts = require('typescript'); -module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, modules, getFileInfo, getExportDocType, getContent, log) { +module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, modules, getFileInfo, + getExportDocType, getContent, log) { return { $runAfter: ['files-read'], @@ -12,8 +13,8 @@ module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, mo $validate: { sourceFiles: {presence: true}, basePath: {presence: true}, - hidePrivateMembers: { inclusion: [true, false] }, - sortClassMembers: { inclusion: [true, false] }, + hidePrivateMembers: {inclusion: [true, false]}, + sortClassMembers: {inclusion: [true, false]}, ignoreExportsMatching: {} }, @@ -64,7 +65,7 @@ module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, mo // Generate docs for each of the export's members if (resolvedExport.flags & ts.SymbolFlags.HasMembers) { - + exportDoc.members = []; for(var memberName in resolvedExport.members) { log.silly('>>>>>> member: ' + memberName + ' from ' + exportDoc.id + ' in ' + moduleDoc.id); @@ -115,6 +116,29 @@ module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, mo } function createExportDoc(name, exportSymbol, moduleDoc, basePath, typeChecker) { + exportSymbol.declarations.forEach(function(decl) { + var sourceFile = ts.getSourceFileOfNode(decl); + if (decl.typeParameters) { + name = name + '<' + getText(sourceFile, decl.typeParameters) + '>'; + } + if (decl.heritageClauses) { + decl.heritageClauses.forEach(function(heritage) { + if (heritage.token == ts.SyntaxKind.ExtendsKeyword) { + name = name + " extends "; + heritage.types.forEach(function(typ, idx) { + name = name + (idx > 0 ? ', ' : '') + typ.getFullText(); + }); + } + if (heritage.token == ts.SyntaxKind.ImplementsKeyword) { + name = name + " implements "; + heritage.types.forEach(function(typ, idx) { + name = name + (idx > 0 ? ', ' : '') + typ.getFullText(); + }); + } + }); + } + }); + var exportDoc = { docType: getExportDocType(exportSymbol), name: name, @@ -167,14 +191,21 @@ module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, mo function getParameters(typeChecker, symbol) { var declaration = symbol.valueDeclaration || symbol.declarations[0]; var sourceFile = ts.getSourceFileOfNode(declaration); - if(!declaration.parameters) { + if (!declaration.parameters) { var location = getLocation(symbol); throw new Error('missing declaration parameters for "' + symbol.name + '" in ' + sourceFile.fileName + ' at line ' + location.start.line); } return declaration.parameters.map(function(parameter) { - return getText(sourceFile, parameter).trim(); + var paramText = getText(sourceFile, parameter.name); + if (parameter.questionToken || parameter.initializer) { + paramText += '?'; + } + if (parameter.type) { + paramText += ':' + getType(sourceFile, parameter.type); + } + return paramText.trim(); }); } @@ -182,7 +213,7 @@ module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, mo var declaration = symbol.valueDeclaration || symbol.declarations[0]; var sourceFile = ts.getSourceFileOfNode(declaration); if (declaration.type) { - return getText(sourceFile, declaration.type).trim(); + return getType(sourceFile, declaration.type).trim(); } } @@ -201,6 +232,18 @@ module.exports = function readTypeScriptModules(tsParser, readFilesProcessor, mo } + // Strip any local renamed imports from the front of types + function getType(sourceFile, type) { + var text = getText(sourceFile, type); + while (text.indexOf(".") >= 0) { + // Keep namespaced symbols in Rx + if (text.match(/^\s*Rx\./)) break; + // handle the case List -> List + text = text.replace(/([^.<]*)\.([^>]*)/, "$2"); + } + return text; + } + function getLocation(symbol) { var node = symbol.valueDeclaration || symbol.declarations[0]; var sourceFile = ts.getSourceFileOfNode(node); diff --git a/docs/dgeni-package/templates/type-definition.template.html b/docs/dgeni-package/templates/type-definition.template.html index 47007c16be..4b1060f522 100644 --- a/docs/dgeni-package/templates/type-definition.template.html +++ b/docs/dgeni-package/templates/type-definition.template.html @@ -6,7 +6,7 @@ {$ '*/' | indent(level, true) | replace(r/\n$/, "") $}{% endif -%} {%- endmacro -%} -// Type definitions for Angular v2.0.0-alpha.22 +// Type definitions for Angular v2.0.0-alpha.26 // Project: http://angular.io/ // Definitions by: angular team // Definitions: https://github.com/borisyankov/DefinitelyTyped @@ -16,6 +16,29 @@ // Please do not create manual edits or send pull requests // modifying this file. // *********************************************************** + +// Angular depends transitively on these libraries. +// If you don't have them installed you can run +// $ tsd query es6-promise rx rx-lite --action install --save +/// +/// + +interface List extends Array {} +interface Map {} +interface StringMap extends Map {} +interface Type {} + +declare module "angular2/angular2" { + type SetterFn = typeof Function; + type int = number; + + // See https://github.com/Microsoft/TypeScript/issues/1168 + class BaseException /* extends Error */ { + message; + stack; + toString(): string; + } +} {% for module in doc.modules %} {$ commentBlock(module, 1) $} declare module "{$ module.id $}" { diff --git a/modules/angular2/angular2.api.dart b/modules/angular2/angular2.api.dart new file mode 100644 index 0000000000..e7d1496a13 --- /dev/null +++ b/modules/angular2/angular2.api.dart @@ -0,0 +1,3 @@ +library angular2.angular2.api; +// Ignore this file for dart emit. +// It is used only for generating the TypeScript .d.ts file. \ No newline at end of file diff --git a/modules/angular2/angular2.api.ts b/modules/angular2/angular2.api.ts new file mode 100644 index 0000000000..41e9c6dcd3 --- /dev/null +++ b/modules/angular2/angular2.api.ts @@ -0,0 +1,28 @@ +// This module is used by dgeni to produce the angular2.d.ts file. + +// Re-export everything we export to the application runtime +export * from './angular2'; + +// Horrible hack. See +// https://docs.google.com/document/d/1nNebWTiLzz5ePcit_bjZPtaiSIFU4EsQKUlX7LX0c0A/edit +// Exports needed to make angular2.d.ts work, +// because these symbols are dependencies of other exports but are not otherwise exported. +// This should be cleaned up in one of two ways: +// 1) if the symbol is intended to be part of the public API, then re-export somewhere else +// 2) if the symbol should be omitted from the public API, then the class exposing it should +// not be exported, or should avoid exposing the symbol. +export {AbstractChangeDetector} from './src/change_detection/abstract_change_detector'; +export {ProtoRecord} from './src/change_detection/proto_record'; +export * from './src/core/compiler/element_injector'; +// FIXME: this is a workaround for https://github.com/angular/angular/issues/2356 +// We export the Directive *annotation* instead of the *decorator*. +// But it breaks the build. +export {Directive, LifecycleEvent} from './src/core/annotations_impl/annotations'; +export {FormDirective} from './src/forms/directives/form_directive'; +export {ControlContainerDirective} from './src/forms/directives/control_container_directive'; +export {Injectable} from './src/di/annotations_impl'; +export {BaseQueryList} from './src/core/compiler/base_query_list'; +export {AppProtoView, AppView, AppViewContainer} from './src/core/compiler/view'; +export * from './src/change_detection/parser/ast'; +export {Visibility} from './src/core/annotations_impl/visibility'; +export {AppViewManager} from './src/core/compiler/view_manager';