diff --git a/.pullapprove.yml b/.pullapprove.yml index 4f6089fa2a..f543ed42a4 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -135,7 +135,6 @@ groups: compiler-cli: conditions: files: - - "packages/tsc-wrapped/*" - "packages/compiler-cli/*" - "packages/bazel/*" users: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9819baeb6d..b1a1bfa2d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -221,7 +221,6 @@ The following is the list of supported scopes: * **platform-webworker-dynamic** * **router** * **upgrade** -* **tsc-wrapped** There are currently a few exceptions to the "use package name" rule: diff --git a/aio/content/guide/metadata.md b/aio/content/guide/metadata.md index 33edf9a7f7..0eb4f93070 100644 --- a/aio/content/guide/metadata.md +++ b/aio/content/guide/metadata.md @@ -66,7 +66,7 @@ You can think of `.metadata.json` as a diagram of the overall structure of a dec
-Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/tsc-wrapped/src/schema.ts) +Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts) describes the JSON format as a collection of TypeScript interfaces.
diff --git a/aio/tools/example-zipper/customizer/package-json/base.json b/aio/tools/example-zipper/customizer/package-json/base.json index d916146ff7..8899065931 100644 --- a/aio/tools/example-zipper/customizer/package-json/base.json +++ b/aio/tools/example-zipper/customizer/package-json/base.json @@ -14,7 +14,6 @@ "@angular/platform-browser-dynamic", "@angular/platform-server", "@angular/router", - "@angular/tsc-wrapped", "@angular/upgrade", "angular-in-memory-web-api", "core-js", diff --git a/aio/tools/examples/example-boilerplate.js b/aio/tools/examples/example-boilerplate.js index bc8944025a..ad64caadc8 100644 --- a/aio/tools/examples/example-boilerplate.js +++ b/aio/tools/examples/example-boilerplate.js @@ -41,7 +41,6 @@ const ANGULAR_PACKAGES = [ 'platform-browser-dynamic', 'platform-server', 'router', - 'tsc-wrapped', 'upgrade', ]; diff --git a/aio/tools/examples/example-boilerplate.spec.js b/aio/tools/examples/example-boilerplate.spec.js index b983e86558..f3484590fb 100644 --- a/aio/tools/examples/example-boilerplate.spec.js +++ b/aio/tools/examples/example-boilerplate.spec.js @@ -26,13 +26,11 @@ describe('example-boilerplate tool', () => { it('should override the Angular node_modules with the locally built Angular packages if `useLocal` is true', () => { const numberOfAngularPackages = 12; - const numberOfAngularToolsPackages = 1; exampleBoilerPlate.add(true); - expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledTimes(numberOfAngularPackages + numberOfAngularToolsPackages); + expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledTimes(numberOfAngularPackages); // for example expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledWith(path.resolve(__dirname, '../../../dist/packages-dist'), 'common'); expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledWith(path.resolve(__dirname, '../../../dist/packages-dist'), 'core'); - expect(exampleBoilerPlate.overridePackage).toHaveBeenCalledWith(path.resolve(__dirname, '../../../dist/packages-dist'), 'tsc-wrapped'); }); it('should process all the example folders', () => { diff --git a/aio/tools/examples/shared/package.json b/aio/tools/examples/shared/package.json index 407fa32f2e..5efa452314 100644 --- a/aio/tools/examples/shared/package.json +++ b/aio/tools/examples/shared/package.json @@ -23,7 +23,6 @@ "@angular/platform-browser-dynamic": "~4.3.1", "@angular/platform-server": "~4.3.1", "@angular/router": "~4.3.1", - "@angular/tsc-wrapped": "~4.3.1", "@angular/upgrade": "~4.3.1", "angular-in-memory-web-api": "~0.4.0", "core-js": "^2.4.1", diff --git a/build.sh b/build.sh index 46ef0fd60d..255dccf96a 100755 --- a/build.sh +++ b/build.sh @@ -25,9 +25,12 @@ PACKAGES=(core language-service benchpress) +TSC_PACKAGES=(compiler-cli + language-service + benchpress) + NODE_PACKAGES=(compiler-cli - benchpress - tsc-wrapped) + benchpress) BUILD_ALL=true BUNDLE=true @@ -38,6 +41,7 @@ BUILD_EXAMPLES=true COMPILE_SOURCE=true TYPECHECK_ALL=true BUILD_TOOLS=true +export NODE_PATH=${NODE_PATH:-}:${currentDir}/dist/tools for ARG in "$@"; do case "$ARG" in @@ -156,7 +160,7 @@ runRollup() { if [[ -f "${1}/rollup.config.js" ]]; then cd ${1} - echo "====== $ROLLUP -c ${1}/rollup.config.js" + echo "====== $ROLLUP -c ${1}/rollup.config.js --sourcemap" $ROLLUP -c rollup.config.js --sourcemap >/dev/null 2>&1 # Recurse for sub directories @@ -216,11 +220,12 @@ minify() { # None ####################################### compilePackage() { - echo "====== [${3}]: COMPILING: ${NGC} -p ${1}/tsconfig-build.json" - # For NODE_PACKAGES items (not getting rolled up) - if containsElement "${3}" "${NODE_PACKAGES[@]}"; then + # For TSC_PACKAGES items + if containsElement "${3}" "${TSC_PACKAGES[@]}"; then + echo "====== [${3}]: COMPILING: ${TSC} -p ${1}/tsconfig-build.json" $TSC -p ${1}/tsconfig-build.json else + echo "====== [${3}]: COMPILING: ${NGC} -p ${1}/tsconfig-build.json" local package_name=$(basename "${2}") $NGC -p ${1}/tsconfig-build.json echo "====== Create ${1}/../${package_name}.d.ts re-export file for tsickle" @@ -247,9 +252,15 @@ compilePackage() { # None ####################################### compilePackageES5() { - echo "====== [${3}]: COMPILING: ${NGC} -p ${1}/tsconfig-build.json --target es5 -d false --outDir ${2} --importHelpers true --sourceMap" - local package_name=$(basename "${2}") - $NGC -p ${1}/tsconfig-build.json --target es5 -d false --outDir ${2} --importHelpers true --sourceMap + if containsElement "${3}" "${TSC_PACKAGES[@]}"; then + echo "====== [${3}]: COMPILING: ${TSC} -p ${1}/tsconfig-build.json --target es5 -d false --outDir ${2} --importHelpers true --sourceMap" + local package_name=$(basename "${2}") + $TSC -p ${1}/tsconfig-build.json --target es5 -d false --outDir ${2} --importHelpers true --sourceMap + else + echo "====== [${3}]: COMPILING: ${NGC} -p ${1}/tsconfig-build.json --target es5 -d false --outDir ${2} --importHelpers true --sourceMap" + local package_name=$(basename "${2}") + $NGC -p ${1}/tsconfig-build.json --target es5 -d false --outDir ${2} --importHelpers true --sourceMap + fi for DIR in ${1}/* ; do [ -d "${DIR}" ] || continue @@ -315,7 +326,7 @@ echo "====== BUILDING: Version ${VERSION}" N=" " TSC=`pwd`/node_modules/.bin/tsc -NGC="node --max-old-space-size=3000 `pwd`/dist/packages-dist/tsc-wrapped/src/main" +NGC="node --max-old-space-size=3000 `pwd`/dist/tools/@angular/compiler-cli/src/main" UGLIFYJS=`pwd`/node_modules/.bin/uglifyjs TSCONFIG=./tools/tsconfig.json ROLLUP=`pwd`/node_modules/.bin/rollup @@ -394,14 +405,12 @@ if [[ ${BUILD_ALL} == true ]]; then fi if [[ ${BUILD_TOOLS} == true || ${BUILD_ALL} == true ]]; then - echo "====== (tsc-wrapped)COMPILING: \$(npm bin)/tsc -p packages/tsc-wrapped/tsconfig.json =====" - $(npm bin)/tsc -p packages/tsc-wrapped/tsconfig.json - echo "====== (tsc-wrapped)COMPILING: \$(npm bin)/tsc -p packages/tsc-wrapped/tsconfig-build.json =====" - $(npm bin)/tsc -p packages/tsc-wrapped/tsconfig-build.json - cp ./packages/tsc-wrapped/package.json ./dist/packages-dist/tsc-wrapped - cp ./packages/tsc-wrapped/README.md ./dist/packages-dist/tsc-wrapped - updateVersionReferences dist/packages-dist/tsc-wrapped + echo "====== (compiler)COMPILING: \$(npm bin)/tsc -p packages/compiler/tsconfig-tools.json" + $(npm bin)/tsc -p packages/compiler/tsconfig-tools.json + echo "====== (compiler)COMPILING: \$(npm bin)/tsc -p packages/compiler-cli/tsconfig-tools.json" + $(npm bin)/tsc -p packages/compiler-cli/tsconfig-tools.json + mkdir -p ./dist/packages-dist rsync -a packages/bazel/ ./dist/packages-dist/bazel # Remove BEGIN-INTERNAL...END-INTERAL blocks # https://stackoverflow.com/questions/24175271/how-can-i-match-multi-line-patterns-in-the-command-line-with-perl-style-regex diff --git a/integration/hello_world__closure/package.json b/integration/hello_world__closure/package.json index f88bed0b6a..61bb2c9bd7 100644 --- a/integration/hello_world__closure/package.json +++ b/integration/hello_world__closure/package.json @@ -10,7 +10,6 @@ "@angular/core": "file:../../dist/packages-dist/core", "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", "@angular/platform-server": "file:../../dist/packages-dist/platform-server", - "@angular/tsc-wrapped": "file:../../dist/packages-dist/tsc-wrapped", "google-closure-compiler": "git+https://github.com/alexeagle/closure-compiler.git#packagejson.dist", "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", diff --git a/integration/i18n/package.json b/integration/i18n/package.json index fb1a67a142..8521427c69 100644 --- a/integration/i18n/package.json +++ b/integration/i18n/package.json @@ -10,7 +10,6 @@ "@angular/core": "file:../../dist/packages-dist/core", "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", "@angular/platform-server": "file:../../dist/packages-dist/platform-server", - "@angular/tsc-wrapped": "file:../../dist/packages-dist/tsc-wrapped", "google-closure-compiler": "git+https://github.com/alexeagle/closure-compiler.git#packagejson.dist", "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", diff --git a/integration/language_service_plugin/package.json b/integration/language_service_plugin/package.json index 44e033ff1c..432a5965fe 100644 --- a/integration/language_service_plugin/package.json +++ b/integration/language_service_plugin/package.json @@ -12,7 +12,6 @@ "@angular/language-service": "file:../../dist/packages-dist/language-service", "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", "@angular/platform-server": "file:../../dist/packages-dist/platform-server", - "@angular/tsc-wrapped": "file:../../dist/packages-dist/tsc-wrapped", "@types/minimist": "^1.2.0", "@types/node": "^7.0.5", "minimist": "^1.2.0", diff --git a/integration/typings_test_ts24/package.json b/integration/typings_test_ts24/package.json index 9876030c6b..33a184bf92 100644 --- a/integration/typings_test_ts24/package.json +++ b/integration/typings_test_ts24/package.json @@ -15,7 +15,6 @@ "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic", "@angular/platform-server": "file:../../dist/packages-dist/platform-server", "@angular/router": "file:../../dist/packages-dist/router", - "@angular/tsc-wrapped": "file:../../dist/packages-dist/tsc-wrapped", "@angular/upgrade": "file:../../dist/packages-dist/upgrade", "@types/jasmine": "2.5.41", "rxjs": "file:../../node_modules/rxjs", diff --git a/karma-js.conf.js b/karma-js.conf.js index 0a8dde14ee..1f9429f186 100644 --- a/karma-js.conf.js +++ b/karma-js.conf.js @@ -61,7 +61,6 @@ module.exports = function(config) { 'dist/all/@angular/examples/**/e2e_test/*', 'dist/all/@angular/language-service/**', 'dist/all/@angular/router/test/**', - 'dist/all/@angular/tsc-wrapped/**', 'dist/all/@angular/platform-browser/testing/e2e_util.js', 'dist/all/angular1_router.js', 'dist/examples/**/e2e_test/**', diff --git a/modules/tsconfig.json b/modules/tsconfig.json index 18bd97a6c3..0c680709d2 100644 --- a/modules/tsconfig.json +++ b/modules/tsconfig.json @@ -12,9 +12,7 @@ "paths": { "selenium-webdriver": ["../node_modules/@types/selenium-webdriver/index.d.ts"], "rxjs/*": ["../node_modules/rxjs/*"], - "@angular/*": ["../dist/all/@angular/*"], - "@angular/tsc-wrapped": ["../dist/packages-dist/tsc-wrapped"], - "@angular/tsc-wrapped/*": ["../dist/packages-dist/tsc-wrapped/*"] + "@angular/*": ["../dist/all/@angular/*"] }, "rootDir": ".", "inlineSourceMap": true, @@ -32,5 +30,8 @@ "benchmarks_external", "payload_tests", "rollup-test" - ] + ], + "angularCompilerOptions": { + "skipTemplateCodegen": true + } } diff --git a/packages/animations/browser/testing/tsconfig-build.json b/packages/animations/browser/testing/tsconfig-build.json index 43fea50fe9..7243eb7bae 100644 --- a/packages/animations/browser/testing/tsconfig-build.json +++ b/packages/animations/browser/testing/tsconfig-build.json @@ -5,7 +5,8 @@ "baseUrl": ".", "rootDir": "../../", "paths": { - "@angular/animations": ["../../../../dist/packages/animations"] + "@angular/animations": ["../../../../dist/packages/animations"], + "@angular/core": ["../../../../dist/packages/core"] }, "outDir": "../../../../dist/packages/animations" }, @@ -19,7 +20,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/animations/browser/testing" } diff --git a/packages/animations/browser/tsconfig-build.json b/packages/animations/browser/tsconfig-build.json index 4a40db325f..4e4dfedb12 100644 --- a/packages/animations/browser/tsconfig-build.json +++ b/packages/animations/browser/tsconfig-build.json @@ -5,7 +5,8 @@ "baseUrl": ".", "rootDir": "../", "paths": { - "@angular/animations": ["../../../dist/packages/animations"] + "@angular/animations": ["../../../dist/packages/animations"], + "@angular/core": ["../../../dist/packages/core"] }, "outDir": "../../../dist/packages/animations" }, @@ -18,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "browser.js", "flatModuleId": "@angular/animations/browser" } diff --git a/packages/animations/tsconfig-build.json b/packages/animations/tsconfig-build.json index 3cd90e155c..f3ecc805f6 100644 --- a/packages/animations/tsconfig-build.json +++ b/packages/animations/tsconfig-build.json @@ -4,7 +4,9 @@ "compilerOptions": { "baseUrl": ".", "rootDir": ".", - "paths": {}, + "paths": { + "@angular/core": ["../../dist/packages/core"] + }, "outDir": "../../dist/packages/animations" }, @@ -16,7 +18,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "animations.js", "flatModuleId": "@angular/animations" } diff --git a/packages/common/http/testing/tsconfig-build.json b/packages/common/http/testing/tsconfig-build.json index a90a2fbaa1..9d37f99383 100644 --- a/packages/common/http/testing/tsconfig-build.json +++ b/packages/common/http/testing/tsconfig-build.json @@ -19,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/common/http/testing" } diff --git a/packages/common/http/tsconfig-build.json b/packages/common/http/tsconfig-build.json index 1c804b0539..39180a20d2 100644 --- a/packages/common/http/tsconfig-build.json +++ b/packages/common/http/tsconfig-build.json @@ -17,7 +17,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "http.js", "flatModuleId": "@angular/common/http" } diff --git a/packages/common/locales/tsconfig-build.json b/packages/common/locales/tsconfig-build.json index e6387189d2..737633495a 100644 --- a/packages/common/locales/tsconfig-build.json +++ b/packages/common/locales/tsconfig-build.json @@ -19,5 +19,8 @@ }, "exclude": [ "./closure-locale.ts" - ] + ], + "angularCompilerOptions": { + "skipTemplateCodegen": true + } } diff --git a/packages/common/testing/tsconfig-build.json b/packages/common/testing/tsconfig-build.json index 840b54605e..c7f5ba334e 100644 --- a/packages/common/testing/tsconfig-build.json +++ b/packages/common/testing/tsconfig-build.json @@ -18,7 +18,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/common/testing" } diff --git a/packages/common/tsconfig-build.json b/packages/common/tsconfig-build.json index 38d55d26c0..1cba80a609 100644 --- a/packages/common/tsconfig-build.json +++ b/packages/common/tsconfig-build.json @@ -17,7 +17,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "common.js", "flatModuleId": "@angular/common" } diff --git a/packages/compiler-cli/BUILD.bazel b/packages/compiler-cli/BUILD.bazel index 3e7e682949..6a0cc0cb2e 100644 --- a/packages/compiler-cli/BUILD.bazel +++ b/packages/compiler-cli/BUILD.bazel @@ -9,8 +9,7 @@ ts_library( ]), module_name = "@angular/compiler-cli", deps = [ - "//packages/compiler", - "//packages/tsc-wrapped", + "//packages/compiler" ], tsconfig = ":tsconfig-build.json", ) diff --git a/packages/compiler-cli/README.md b/packages/compiler-cli/README.md index 074a9ec499..5cb161c59b 100644 --- a/packages/compiler-cli/README.md +++ b/packages/compiler-cli/README.md @@ -112,7 +112,7 @@ with the one already used in the plugin for TypeScript typechecking and emit. ## Design At a high level, this program -- collects static metadata about the sources using the `tsc-wrapped` package +- collects static metadata about the sources - uses the `OfflineCompiler` from `@angular/compiler` to codegen additional `.ts` files - these `.ts` files are written to the `genDir` path, then compiled together with the application. @@ -130,7 +130,7 @@ $ ./scripts/ci/offline_compiler_test.sh # Recompile @angular/core module (needs to use tsc-ext to keep the metadata) $ export NODE_PATH=${NODE_PATH}:$(pwd)/dist/all:$(pwd)/dist/tools -$ node dist/tools/@angular/tsc-wrapped/src/main -p packages/core/tsconfig-build.json +$ node dist/tools/@angular/compiler-cli/src/main -p packages/core/tsconfig-build.json # Iterate on the test $ cd /tmp/wherever/e2e_test.1464388257/ diff --git a/packages/compiler-cli/browser-rollup.config.js b/packages/compiler-cli/browser-rollup.config.js index 1de437b635..99abce4464 100644 --- a/packages/compiler-cli/browser-rollup.config.js +++ b/packages/compiler-cli/browser-rollup.config.js @@ -17,10 +17,7 @@ var rxjsLocation = normalize('../../node_modules/rxjs'); var tslibLocation = normalize('../../node_modules/tslib'); var esm = 'esm/'; -var locations = { - 'tsc-wrapped': normalize('../../dist/tools/@angular') + '/', - 'compiler-cli': normalize('../../dist/packages') + '/' -}; +var locations = {'compiler-cli': normalize('../../dist/packages') + '/'}; var esm_suffixes = {}; @@ -30,11 +27,6 @@ function normalize(fileName) { function resolve(id, from) { // console.log('Resolve id:', id, 'from', from) - if (id == '@angular/tsc-wrapped') { - // Hack to restrict the import to not include the index of @angular/tsc-wrapped so we don't - // rollup tsickle. - return locations['tsc-wrapped'] + 'tsc-wrapped/src/collector.js'; - } var match = m.exec(id); if (match) { var packageName = match[1]; diff --git a/packages/compiler-cli/integrationtest/test/test_ngtools_api.ts b/packages/compiler-cli/integrationtest/test/test_ngtools_api.ts index f1ff609bc2..0e6fd02751 100644 --- a/packages/compiler-cli/integrationtest/test/test_ngtools_api.ts +++ b/packages/compiler-cli/integrationtest/test/test_ngtools_api.ts @@ -14,8 +14,7 @@ import 'reflect-metadata'; import * as path from 'path'; import * as ts from 'typescript'; import * as assert from 'assert'; -import {tsc} from '@angular/tsc-wrapped/src/tsc'; -import {__NGTOOLS_PRIVATE_API_2} from '@angular/compiler-cli'; +import {__NGTOOLS_PRIVATE_API_2, readConfiguration} from '@angular/compiler-cli'; const glob = require('glob'); @@ -50,14 +49,14 @@ function codeGenTest(forceError = false) { const readResources: string[] = []; const wroteFiles: string[] = []; - const config = tsc.readConfiguration(project, basePath); - const delegateHost = ts.createCompilerHost(config.parsed.options, true); + const config = readConfiguration(project); + const delegateHost = ts.createCompilerHost(config.options, true); const host: ts.CompilerHost = Object.assign( {}, delegateHost, {writeFile: (fileName: string, ...rest: any[]) => { wroteFiles.push(fileName); }}); - const program = ts.createProgram(config.parsed.fileNames, config.parsed.options, host); + const program = ts.createProgram(config.rootNames, config.options, host); - config.ngOptions.basePath = basePath; + config.options.basePath = basePath; console.log(`>>> running codegen for ${project}`); if (forceError) { @@ -66,9 +65,9 @@ function codeGenTest(forceError = false) { return __NGTOOLS_PRIVATE_API_2 .codeGen({ basePath, - compilerOptions: config.parsed.options, program, host, + compilerOptions: config.options, program, host, - angularCompilerOptions: config.ngOptions, + angularCompilerOptions: config.options, // i18n options. i18nFormat: 'xlf', @@ -129,21 +128,21 @@ function i18nTest() { const readResources: string[] = []; const wroteFiles: string[] = []; - const config = tsc.readConfiguration(project, basePath); - const delegateHost = ts.createCompilerHost(config.parsed.options, true); + const config = readConfiguration(project); + const delegateHost = ts.createCompilerHost(config.options, true); const host: ts.CompilerHost = Object.assign( {}, delegateHost, {writeFile: (fileName: string, ...rest: any[]) => { wroteFiles.push(fileName); }}); - const program = ts.createProgram(config.parsed.fileNames, config.parsed.options, host); + const program = ts.createProgram(config.rootNames, config.options, host); - config.ngOptions.basePath = basePath; + config.options.basePath = basePath; console.log(`>>> running i18n extraction for ${project}`); return __NGTOOLS_PRIVATE_API_2 .extractI18n({ basePath, - compilerOptions: config.parsed.options, program, host, - angularCompilerOptions: config.ngOptions, + compilerOptions: config.options, program, host, + angularCompilerOptions: config.options, i18nFormat: 'xlf', locale: undefined, outFile: undefined, @@ -193,18 +192,14 @@ function lazyRoutesTest() { const basePath = path.join(__dirname, '../ngtools_src'); const project = path.join(basePath, 'tsconfig-build.json'); - const config = tsc.readConfiguration(project, basePath); - const host = ts.createCompilerHost(config.parsed.options, true); - const program = ts.createProgram(config.parsed.fileNames, config.parsed.options, host); + const config = readConfiguration(project); + const host = ts.createCompilerHost(config.options, true); + const program = ts.createProgram(config.rootNames, config.options, host); - config.ngOptions.basePath = basePath; + config.options.basePath = basePath; - const lazyRoutes = __NGTOOLS_PRIVATE_API_2.listLazyRoutes({ - program, - host, - angularCompilerOptions: config.ngOptions, - entryModule: 'app.module#AppModule' - }); + const lazyRoutes = __NGTOOLS_PRIVATE_API_2.listLazyRoutes( + {program, host, angularCompilerOptions: config.options, entryModule: 'app.module#AppModule'}); const expectations: {[route: string]: string} = { './lazy.module#LazyModule': 'lazy.module.ts', diff --git a/packages/compiler-cli/integrationtest/test/test_summaries.ts b/packages/compiler-cli/integrationtest/test/test_summaries.ts index e73b1cf2df..da61dadb13 100644 --- a/packages/compiler-cli/integrationtest/test/test_summaries.ts +++ b/packages/compiler-cli/integrationtest/test/test_summaries.ts @@ -14,8 +14,7 @@ import 'reflect-metadata'; import * as path from 'path'; import * as ts from 'typescript'; import * as assert from 'assert'; -import {tsc} from '@angular/tsc-wrapped/src/tsc'; -import {CompilerOptions, CodeGenerator, CompilerHostContext, NodeCompilerHostContext} from '@angular/compiler-cli'; +import {CompilerOptions, CodeGenerator, CompilerHostContext, NodeCompilerHostContext, readConfiguration} from '@angular/compiler-cli'; /** * Main method. @@ -46,10 +45,10 @@ function main() { } } - const config = tsc.readConfiguration(project, basePath); - config.ngOptions.basePath = basePath; + const config = readConfiguration(project); + config.options.basePath = basePath; // This flag tells ngc do not recompile libraries. - config.ngOptions.generateCodeForLibraries = false; + config.options.generateCodeForLibraries = false; console.log(`>>> running codegen for ${project}`); codegen( @@ -86,21 +85,21 @@ function main() { } /** - * Simple adaption of tsc-wrapped main to just run codegen with a CompilerHostContext + * Simple adaption of main to just run codegen with a CompilerHostContext */ function codegen( - config: {parsed: ts.ParsedCommandLine, ngOptions: CompilerOptions}, + config: {options: CompilerOptions, rootNames: string[]}, hostContextFactory: (host: ts.CompilerHost) => CompilerHostContext) { - const host = ts.createCompilerHost(config.parsed.options, true); + const host = ts.createCompilerHost(config.options, true); // HACK: patch the realpath to solve symlink issue here: // https://github.com/Microsoft/TypeScript/issues/9552 // todo(misko): remove once facade symlinks are removed host.realpath = (path) => path; - const program = ts.createProgram(config.parsed.fileNames, config.parsed.options, host); + const program = ts.createProgram(config.rootNames, config.options, host); - return CodeGenerator.create(config.ngOptions, { + return CodeGenerator.create(config.options, { } as any, program, host, hostContextFactory(host)).codegen(); } diff --git a/packages/compiler-cli/package.json b/packages/compiler-cli/package.json index 5db3b7a3e9..c5ffae08f9 100644 --- a/packages/compiler-cli/package.json +++ b/packages/compiler-cli/package.json @@ -9,7 +9,6 @@ "ng-xi18n": "./src/extract_i18n.js" }, "dependencies": { - "@angular/tsc-wrapped": "5.0.0-beta.7", "reflect-metadata": "^0.1.2", "minimist": "^1.2.0", "tsickle": "^0.24.0", diff --git a/packages/compiler-cli/src/transformers/compiler_host.ts b/packages/compiler-cli/src/transformers/compiler_host.ts index aa27c24e3e..0017a7ad37 100644 --- a/packages/compiler-cli/src/transformers/compiler_host.ts +++ b/packages/compiler-cli/src/transformers/compiler_host.ts @@ -431,6 +431,10 @@ function addReferencesToSourceFile(sf: ts.SourceFile, genFileNames: string[]) { sf.referencedFiles = newReferencedFiles; } +export function getOriginalReferences(sourceFile: ts.SourceFile): ts.FileReference[]|undefined { + return sourceFile && (sourceFile as any).originalReferencedFiles; +} + function dotRelative(from: string, to: string): string { const rPath: string = path.relative(from, to).replace(/\\/g, '/'); return rPath.startsWith('.') ? rPath : './' + rPath; diff --git a/packages/compiler-cli/src/transformers/program.ts b/packages/compiler-cli/src/transformers/program.ts index 5d82e89017..26b3edc417 100644 --- a/packages/compiler-cli/src/transformers/program.ts +++ b/packages/compiler-cli/src/transformers/program.ts @@ -15,7 +15,7 @@ import {TypeCheckHost, translateDiagnostics} from '../diagnostics/translate_diag import {ModuleMetadata, createBundleIndexHost} from '../metadata/index'; import {CompilerHost, CompilerOptions, CustomTransformers, DEFAULT_ERROR_CODE, Diagnostic, EmitFlags, Program, SOURCE, TsEmitArguments, TsEmitCallback} from './api'; -import {TsCompilerAotCompilerTypeCheckHostAdapter} from './compiler_host'; +import {TsCompilerAotCompilerTypeCheckHostAdapter, getOriginalReferences} from './compiler_host'; import {LowerMetadataCache, getExpressionLoweringTransformFactory} from './lower_expressions'; import {getAngularEmitterTransformFactory} from './node_emitter_transform'; import {GENERATED_FILES, StructureIsReused, tsStructureIsReused} from './util'; @@ -173,15 +173,34 @@ class AngularCompilerProgram implements Program { }; } - const emitResult = emitCallback({ - program: this.tsProgram, - host: this.host, - options: this.options, - writeFile: createWriteFileCallback(genFiles, this.host, outSrcMapping), - emitOnlyDtsFiles: (emitFlags & (EmitFlags.DTS | EmitFlags.JS)) == EmitFlags.DTS, - customTransformers: this.calculateTransforms(genFiles, customTransformers) - }); + // Restore the original references before we emit so TypeScript doesn't emit + // a reference to the .d.ts file. + const augmentedReferences = new Map(); + for (const sourceFile of this.tsProgram.getSourceFiles()) { + const originalReferences = getOriginalReferences(sourceFile); + if (originalReferences) { + augmentedReferences.set(sourceFile, sourceFile.referencedFiles); + sourceFile.referencedFiles = originalReferences; + } + } + let emitResult: ts.EmitResult; + try { + emitResult = emitCallback({ + program: this.tsProgram, + host: this.host, + options: this.options, + writeFile: createWriteFileCallback(genFiles, this.host, outSrcMapping), + emitOnlyDtsFiles: (emitFlags & (EmitFlags.DTS | EmitFlags.JS)) == EmitFlags.DTS, + customTransformers: this.calculateTransforms(genFiles, customTransformers) + }); + } finally { + // Restore the references back to the augmented value to ensure that the + // checks that TypeScript makes for project structure reuse will succeed. + for (const [sourceFile, references] of Array.from(augmentedReferences)) { + sourceFile.referencedFiles = references; + } + } if (!outSrcMapping.length) { // if no files were emitted by TypeScript, also don't emit .json files @@ -464,6 +483,7 @@ function getAotCompilerOptions(options: CompilerOptions): AotCompilerOptions { enableSummariesForJit: true, preserveWhitespaces: options.preserveWhitespaces, fullTemplateTypeCheck: options.fullTemplateTypeCheck, + rootDir: options.rootDir, }; } diff --git a/packages/compiler-cli/test/diagnostics/check_types_spec.ts b/packages/compiler-cli/test/diagnostics/check_types_spec.ts index 7d26284af0..8069f5add2 100644 --- a/packages/compiler-cli/test/diagnostics/check_types_spec.ts +++ b/packages/compiler-cli/test/diagnostics/check_types_spec.ts @@ -8,6 +8,7 @@ import * as ng from '@angular/compiler-cli'; import * as fs from 'fs'; +import * as os from 'os'; import * as path from 'path'; import * as ts from 'typescript'; @@ -247,3 +248,12 @@ const LOWERING_QUICKSTART = { export class AppModule { } ` }; + +const tmpdir = process.env.TEST_TMPDIR || os.tmpdir(); + +function makeTempDir(): string { + const id = (Math.random() * 1000000).toFixed(0); + const dir = path.join(tmpdir, `tmp.${id}`); + fs.mkdirSync(dir); + return dir; +} diff --git a/packages/compiler-cli/tsconfig-build.json b/packages/compiler-cli/tsconfig-build.json index d474f82d9f..866795a045 100644 --- a/packages/compiler-cli/tsconfig-build.json +++ b/packages/compiler-cli/tsconfig-build.json @@ -8,8 +8,7 @@ "baseUrl": ".", "rootDir": ".", "paths": { - "@angular/compiler": ["../../dist/packages/compiler"], - "@angular/tsc-wrapped": ["../../dist/packages-dist/tsc-wrapped"] + "@angular/compiler": ["../../dist/packages/compiler"] }, "outDir": "../../dist/packages/compiler-cli" }, diff --git a/packages/compiler-cli/tsconfig-tools.json b/packages/compiler-cli/tsconfig-tools.json new file mode 100644 index 0000000000..752f6bf1ed --- /dev/null +++ b/packages/compiler-cli/tsconfig-tools.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig-build.json", + + "compilerOptions": { + "outDir": "../../dist/tools/@angular/compiler-cli", + "paths": { + "@angular/compiler": ["../../dist/tools/@angular/compiler"] + } + } +} \ No newline at end of file diff --git a/packages/compiler/src/aot/compiler.ts b/packages/compiler/src/aot/compiler.ts index 47e32dfe93..69cdfd61be 100644 --- a/packages/compiler/src/aot/compiler.ts +++ b/packages/compiler/src/aot/compiler.ts @@ -27,6 +27,7 @@ import {TypeCheckCompiler} from '../view_compiler/type_check_compiler'; import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler'; import {AotCompilerHost} from './compiler_host'; +import {AotCompilerOptions} from './compiler_options'; import {GeneratedFile} from './generated_file'; import {StaticReflector} from './static_reflector'; import {StaticSymbol} from './static_symbol'; @@ -45,16 +46,14 @@ export class AotCompiler { new Map(); constructor( - private _config: CompilerConfig, private _host: AotCompilerHost, - private _reflector: StaticReflector, private _metadataResolver: CompileMetadataResolver, - private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler, - private _viewCompiler: ViewCompiler, private _typeCheckCompiler: TypeCheckCompiler, - private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter, - private _summaryResolver: SummaryResolver, private _localeId: string|null, - private _translationFormat: string|null, - /** TODO(tbosch): remove this flag as it is always on in the new ngc */ - private _enableSummariesForJit: boolean|null, private _symbolResolver: StaticSymbolResolver) { - } + private _config: CompilerConfig, private options: AotCompilerOptions, + private _host: AotCompilerHost, private _reflector: StaticReflector, + private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser, + private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler, + private _typeCheckCompiler: TypeCheckCompiler, private _ngModuleCompiler: NgModuleCompiler, + private _outputEmitter: OutputEmitter, + private _summaryResolver: SummaryResolver, + private _symbolResolver: StaticSymbolResolver) {} clearCache() { this._metadataResolver.clearCache(); } @@ -121,7 +120,8 @@ export class AotCompiler { private _createNgFactoryStub(file: NgAnalyzedFile, emitFlags: StubEmitFlags): GeneratedFile[] { const generatedFiles: GeneratedFile[] = []; - const outputCtx = this._createOutputContext(ngfactoryFilePath(file.fileName, true)); + const outputCtx = this._createOutputContext( + calculateGenFileName(ngfactoryFilePath(file.fileName, true), this.options.rootDir)); file.ngModules.forEach((ngModuleMeta, ngModuleIndex) => { // Note: the code below needs to executed for StubEmitFlags.Basic and StubEmitFlags.TypeCheck, @@ -209,8 +209,10 @@ export class AotCompiler { } const encapsulation = compMeta.template !.encapsulation || this._config.defaultEncapsulation; - const outputCtx = this._createOutputContext(_stylesModuleUrl( - normalizedUrl, encapsulation === ViewEncapsulation.Emulated, fileSuffix)); + const outputCtx = this._createOutputContext(calculateGenFileName( + _stylesModuleUrl( + normalizedUrl, encapsulation === ViewEncapsulation.Emulated, fileSuffix), + this.options.rootDir)); _createEmptyStub(outputCtx); generatedFiles.push(this._codegenSourceModule(normalizedUrl, outputCtx)); }); @@ -221,12 +223,13 @@ export class AotCompiler { private _createNgSummaryStub(file: NgAnalyzedFile, emitFlags: StubEmitFlags): GeneratedFile[] { const generatedFiles: GeneratedFile[] = []; // note: .ngsummary.js stubs don't change when we produce type check stubs - if (!this._enableSummariesForJit || !(emitFlags & StubEmitFlags.Basic)) { + if (!this.options.enableSummariesForJit || !(emitFlags & StubEmitFlags.Basic)) { return generatedFiles; } if (file.directives.length || file.injectables.length || file.ngModules.length || file.pipes.length || file.exportsNonSourceFiles) { - const outputCtx = this._createOutputContext(summaryForJitFileName(file.fileName, true)); + const outputCtx = this._createOutputContext( + calculateGenFileName(summaryForJitFileName(file.fileName, true), this.options.rootDir)); file.ngModules.forEach(ngModule => { // create exports that user code can reference createForJitStub(outputCtx, ngModule.type.reference); @@ -295,7 +298,8 @@ export class AotCompiler { const fileSuffix = splitTypescriptSuffix(srcFileUrl, true)[1]; const generatedFiles: GeneratedFile[] = []; - const outputCtx = this._createOutputContext(ngfactoryFilePath(srcFileUrl, true)); + const outputCtx = this._createOutputContext( + calculateGenFileName(ngfactoryFilePath(srcFileUrl, true), this.options.rootDir)); generatedFiles.push( ...this._createSummary(srcFileUrl, directives, pipes, ngModules, injectables, outputCtx)); @@ -366,7 +370,8 @@ export class AotCompiler { metadata: this._metadataResolver.getInjectableSummary(ref) !.type })) ]; - const forJitOutputCtx = this._createOutputContext(summaryForJitFileName(srcFileName, true)); + const forJitOutputCtx = this._createOutputContext( + calculateGenFileName(summaryForJitFileName(srcFileName, true), this.options.rootDir)); const {json, exportAs} = serializeSummaries( srcFileName, forJitOutputCtx, this._summaryResolver, this._symbolResolver, symbolSummaries, typeData); @@ -377,7 +382,7 @@ export class AotCompiler { ])); }); const summaryJson = new GeneratedFile(srcFileName, summaryFileName(srcFileName), json); - if (this._enableSummariesForJit) { + if (this.options.enableSummariesForJit) { return [summaryJson, this._codegenSourceModule(srcFileName, forJitOutputCtx)]; }; @@ -387,18 +392,18 @@ export class AotCompiler { private _compileModule(outputCtx: OutputContext, ngModule: CompileNgModuleMetadata): void { const providers: CompileProviderMetadata[] = []; - if (this._localeId) { - const normalizedLocale = this._localeId.replace(/_/g, '-'); + if (this.options.locale) { + const normalizedLocale = this.options.locale.replace(/_/g, '-'); providers.push({ token: createTokenForExternalReference(this._reflector, Identifiers.LOCALE_ID), useValue: normalizedLocale, }); } - if (this._translationFormat) { + if (this.options.i18nFormat) { providers.push({ token: createTokenForExternalReference(this._reflector, Identifiers.TRANSLATIONS_FORMAT), - useValue: this._translationFormat + useValue: this.options.i18nFormat }); } @@ -516,8 +521,11 @@ export class AotCompiler { private _codegenStyles( srcFileUrl: string, compMeta: CompileDirectiveMetadata, stylesheetMetadata: CompileStylesheetMetadata, fileSuffix: string): GeneratedFile { - const outputCtx = this._createOutputContext(_stylesModuleUrl( - stylesheetMetadata.moduleUrl !, this._styleCompiler.needsStyleShim(compMeta), fileSuffix)); + const outputCtx = this._createOutputContext(calculateGenFileName( + _stylesModuleUrl( + stylesheetMetadata.moduleUrl !, this._styleCompiler.needsStyleShim(compMeta), + fileSuffix), + this.options.rootDir)); const compiledStylesheet = this._styleCompiler.compileStyles(outputCtx, compMeta, stylesheetMetadata); _resolveStyleStatements( @@ -723,3 +731,17 @@ export function mergeAnalyzedFiles(analyzedFiles: NgAnalyzedFile[]): NgAnalyzedM function mergeAndValidateNgFiles(files: NgAnalyzedFile[]): NgAnalyzedModules { return validateAnalyzedModules(mergeAnalyzedFiles(files)); } + +function calculateGenFileName(fileName: string, rootDir: string | undefined): string { + if (!rootDir) return fileName; + + const fileNameParts = fileName.split(/\\|\//); + const rootDirParts = rootDir.split(/\\|\//); + if (!rootDirParts[rootDirParts.length - 1]) rootDirParts.pop(); + let i = 0; + while (i < Math.min(fileNameParts.length, rootDirParts.length) && + fileNameParts[i] === rootDirParts[i]) + i++; + const result = [...rootDirParts, ...fileNameParts.slice(i)].join('/'); + return result; +} \ No newline at end of file diff --git a/packages/compiler/src/aot/compiler_factory.ts b/packages/compiler/src/aot/compiler_factory.ts index eab1c57e5a..c794269b05 100644 --- a/packages/compiler/src/aot/compiler_factory.ts +++ b/packages/compiler/src/aot/compiler_factory.ts @@ -84,9 +84,9 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom const viewCompiler = new ViewCompiler(staticReflector); const typeCheckCompiler = new TypeCheckCompiler(options, staticReflector); const compiler = new AotCompiler( - config, compilerHost, staticReflector, resolver, tmplParser, new StyleCompiler(urlResolver), - viewCompiler, typeCheckCompiler, new NgModuleCompiler(staticReflector), - new TypeScriptEmitter(), summaryResolver, options.locale || null, options.i18nFormat || null, - options.enableSummariesForJit || null, symbolResolver); + config, options, compilerHost, staticReflector, resolver, tmplParser, + new StyleCompiler(urlResolver), viewCompiler, typeCheckCompiler, + new NgModuleCompiler(staticReflector), new TypeScriptEmitter(), summaryResolver, + symbolResolver); return {compiler, reflector: staticReflector}; } diff --git a/packages/compiler/src/aot/compiler_options.ts b/packages/compiler/src/aot/compiler_options.ts index 662ee488dc..784d765342 100644 --- a/packages/compiler/src/aot/compiler_options.ts +++ b/packages/compiler/src/aot/compiler_options.ts @@ -17,4 +17,5 @@ export interface AotCompilerOptions { enableSummariesForJit?: boolean; preserveWhitespaces?: boolean; fullTemplateTypeCheck?: boolean; + rootDir?: string; } diff --git a/packages/compiler/testing/index.ts b/packages/compiler/testing/index.ts index e727e2e8a7..b2406f1bd8 100644 --- a/packages/compiler/testing/index.ts +++ b/packages/compiler/testing/index.ts @@ -11,4 +11,4 @@ // replaces this file with production index.ts when it rewrites private symbol // names. -export * from './public_api'; +export * from './testing'; diff --git a/packages/compiler/testing/testing.ts b/packages/compiler/testing/testing.ts new file mode 100644 index 0000000000..ca39d26dcd --- /dev/null +++ b/packages/compiler/testing/testing.ts @@ -0,0 +1,14 @@ +/** + * @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 + */ + +// This file is not used to build this module. It is only used during editing +// by the TypeScript language service and during build for verification. `ngc` +// replaces this file with production index.ts when it rewrites private symbol +// names. + +export * from './public_api'; \ No newline at end of file diff --git a/packages/compiler/testing/tsconfig-build.json b/packages/compiler/testing/tsconfig-build.json index 1fbc333d5c..48f35ad786 100644 --- a/packages/compiler/testing/tsconfig-build.json +++ b/packages/compiler/testing/tsconfig-build.json @@ -5,19 +5,20 @@ "baseUrl": ".", "rootDir": "../", "paths": { - "@angular/compiler": ["../../../dist/packages/compiler"] + "@angular/compiler": ["../../../dist/packages/compiler"], + "@angular/core": ["../../../dist/packages/core"] }, "outDir": "../../../dist/packages/compiler" }, "files": [ - "public_api.ts", + "testing.ts", "../../../node_modules/zone.js/dist/zone.js.d.ts" ], "angularCompilerOptions": { "annotateForClosureCompiler": true, - "flatModuleOutFile": "testing.js", - "flatModuleId": "@angular/compiler/testing" + "skipMetadataEmit": true, + "skipTemplateCodegen": true } } diff --git a/packages/compiler/tsconfig-build.json b/packages/compiler/tsconfig-build.json index 27d4084c32..46fbc6492f 100644 --- a/packages/compiler/tsconfig-build.json +++ b/packages/compiler/tsconfig-build.json @@ -11,6 +11,9 @@ "module": "es2015", "moduleResolution": "node", "outDir": "../../dist/packages/compiler", + "paths": { + "@angular/core": ["../../dist/packages/core"] + }, "rootDir": ".", "sourceMap": true, "inlineSources": true, @@ -23,5 +26,11 @@ "files": [ "index.ts", "../../node_modules/zone.js/dist/zone.js.d.ts" - ] + ], + + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipMetadataEmit": true, + "skipTemplateCodegen": true + } } diff --git a/packages/compiler/tsconfig-tools.json b/packages/compiler/tsconfig-tools.json new file mode 100644 index 0000000000..e45b55988d --- /dev/null +++ b/packages/compiler/tsconfig-tools.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig-build.json", + + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "outDir": "../../dist/tools/@angular/compiler" + } +} \ No newline at end of file diff --git a/packages/core/testing/tsconfig-build.json b/packages/core/testing/tsconfig-build.json index c3fb9a5521..47785208d0 100644 --- a/packages/core/testing/tsconfig-build.json +++ b/packages/core/testing/tsconfig-build.json @@ -18,7 +18,8 @@ ], "angularCompilerOptions": { - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/core/testing" } diff --git a/packages/core/tsconfig-build.json b/packages/core/tsconfig-build.json index 62df311949..50c1ffdf24 100644 --- a/packages/core/tsconfig-build.json +++ b/packages/core/tsconfig-build.json @@ -5,7 +5,8 @@ "baseUrl": ".", "rootDir": ".", "paths": { - "rxjs/*": ["../../node_modules/rxjs/*"] + "rxjs/*": ["../../node_modules/rxjs/*"], + "@angular/core": ["."] }, "outDir": "../../dist/packages/core" }, @@ -18,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "core.js", "flatModuleId": "@angular/core" } diff --git a/packages/forms/tsconfig-build.json b/packages/forms/tsconfig-build.json index cd1a0b1ec3..d766f005fe 100644 --- a/packages/forms/tsconfig-build.json +++ b/packages/forms/tsconfig-build.json @@ -23,7 +23,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "forms.js", "flatModuleId": "@angular/forms" } diff --git a/packages/http/testing/tsconfig-build.json b/packages/http/testing/tsconfig-build.json index 4043e93200..caef5194fb 100644 --- a/packages/http/testing/tsconfig-build.json +++ b/packages/http/testing/tsconfig-build.json @@ -18,7 +18,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/http/testing" } diff --git a/packages/http/tsconfig-build.json b/packages/http/tsconfig-build.json index 7426f25c1b..4c42fd5359 100644 --- a/packages/http/tsconfig-build.json +++ b/packages/http/tsconfig-build.json @@ -19,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "http.js", "flatModuleId": "@angular/http" } diff --git a/packages/language-service/rollup.config.js b/packages/language-service/rollup.config.js index 23822d0030..aeca7bb347 100644 --- a/packages/language-service/rollup.config.js +++ b/packages/language-service/rollup.config.js @@ -16,10 +16,7 @@ var rxjsLocation = normalize('../../node_modules/rxjs'); var tslibLocation = normalize('../../node_modules/tslib'); var esm = 'esm/'; -var locations = { - 'tsc-wrapped': normalize('../../dist/packages-dist') + '/', - 'compiler-cli': normalize('../../dist/packages') + '/' -}; +var locations = {'compiler-cli': normalize('../../dist/packages') + '/'}; var esm_suffixes = {}; @@ -29,11 +26,6 @@ function normalize(fileName) { function resolve(id, from) { // console.log('Resolve id:', id, 'from', from) - if (id == '@angular/tsc-wrapped') { - // Hack to restrict the import to not include the index of @angular/tsc-wrapped so we don't - // rollup tsickle. - return locations['tsc-wrapped'] + 'tsc-wrapped/src/collector.js'; - } var match = m.exec(id); if (match) { var packageName = match[1]; diff --git a/packages/language-service/tsconfig-build.json b/packages/language-service/tsconfig-build.json index 0dcf035db5..5641c2bd19 100644 --- a/packages/language-service/tsconfig-build.json +++ b/packages/language-service/tsconfig-build.json @@ -16,9 +16,7 @@ "@angular/compiler-cli/*": ["../../dist/packages/compiler-cli/*"], "@angular/http": ["../../dist/packages/http"], "@angular/platform-server": ["../../dist/packages/platform-server"], - "@angular/platform-browser": ["../../dist/packages/platform-browser"], - "@angular/tsc-wrapped": ["../../dist/packages-dist/tsc-wrapped"], - "@angular/tsc-wrapped/*": ["../../dist/packages-dist/tsc-wrapped/*"] + "@angular/platform-browser": ["../../dist/packages/platform-browser"] }, "outDir": "../../dist/packages/language-service" }, diff --git a/packages/platform-browser-dynamic/testing/tsconfig-build.json b/packages/platform-browser-dynamic/testing/tsconfig-build.json index 9affe5bfca..398fe63fc5 100644 --- a/packages/platform-browser-dynamic/testing/tsconfig-build.json +++ b/packages/platform-browser-dynamic/testing/tsconfig-build.json @@ -26,7 +26,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/platform-browser-dynamic/testing" } diff --git a/packages/platform-browser-dynamic/tsconfig-build.json b/packages/platform-browser-dynamic/tsconfig-build.json index 789f38a871..27dabc973f 100644 --- a/packages/platform-browser-dynamic/tsconfig-build.json +++ b/packages/platform-browser-dynamic/tsconfig-build.json @@ -25,7 +25,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "platform-browser-dynamic.js", "flatModuleId": "@angular/platform-browser-dynamic" } diff --git a/packages/platform-browser/animations/tsconfig-build.json b/packages/platform-browser/animations/tsconfig-build.json index 047c7c2bda..b0f35fcdd6 100644 --- a/packages/platform-browser/animations/tsconfig-build.json +++ b/packages/platform-browser/animations/tsconfig-build.json @@ -6,6 +6,7 @@ "rootDir": "../", "paths": { "rxjs/*": ["../../../node_modules/rxjs/*"], + "@angular/common": ["../../../dist/packages/common"], "@angular/core": ["../../../dist/packages/core"], "@angular/core/testing": ["../../../dist/packages/core/testing"], "@angular/animations": ["../../../dist/packages/animations"], @@ -23,7 +24,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "animations.js", "flatModuleId": "@angular/platform-browser/animations" } diff --git a/packages/platform-browser/testing/tsconfig-build.json b/packages/platform-browser/testing/tsconfig-build.json index 03f2b5bf14..41f39c9aca 100644 --- a/packages/platform-browser/testing/tsconfig-build.json +++ b/packages/platform-browser/testing/tsconfig-build.json @@ -23,7 +23,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/platform-browser/testing" } diff --git a/packages/platform-browser/tsconfig-build.json b/packages/platform-browser/tsconfig-build.json index dd0a58f6b8..cf4b567c7e 100644 --- a/packages/platform-browser/tsconfig-build.json +++ b/packages/platform-browser/tsconfig-build.json @@ -20,7 +20,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "platform-browser.js", "flatModuleId": "@angular/platform-browser" } diff --git a/packages/platform-server/integrationtest/package.json b/packages/platform-server/integrationtest/package.json index 51c4428379..9471392bc0 100644 --- a/packages/platform-server/integrationtest/package.json +++ b/packages/platform-server/integrationtest/package.json @@ -12,7 +12,6 @@ "@angular/common": "file:../../../dist/packages-dist/common", "@angular/compiler": "file:../../../dist/packages-dist/compiler", "@angular/compiler-cli": "file:../../../dist/packages-dist/compiler-cli", - "@angular/tsc-wrapped": "file:../../../dist/packages-dist/tsc-wrapped", "@angular/core": "file:../../../dist/packages-dist/core", "@angular/http": "file:../../../dist/packages-dist/http", "@angular/platform-browser": "file:../../../dist/packages-dist/platform-browser", diff --git a/packages/platform-server/testing/tsconfig-build.json b/packages/platform-server/testing/tsconfig-build.json index 1637daad7b..b5aa98165d 100644 --- a/packages/platform-server/testing/tsconfig-build.json +++ b/packages/platform-server/testing/tsconfig-build.json @@ -5,13 +5,16 @@ "baseUrl": ".", "rootDir": "../", "paths": { + "@angular/animations": ["../../../dist/packages/animations"], "@angular/animations/browser": ["../../../dist/packages/animations/browser"], "@angular/core": ["../../../dist/packages/core"], "@angular/core/testing": ["../../../dist/packages/core/testing"], "@angular/common": ["../../../dist/packages/common"], + "@angular/common/http": ["../../../dist/packages/common/http"], "@angular/common/testing": ["../../../dist/packages/common/testing"], "@angular/compiler": ["../../../dist/packages/compiler"], "@angular/compiler/testing": ["../../../dist/packages/compiler/testing"], + "@angular/http": ["../../../dist/packages/http"], "@angular/platform-browser": ["../../../dist/packages/platform-browser"], "@angular/platform-browser/animations": ["../../../dist/packages/platform-browser/animations"], "@angular/platform-browser/testing": ["../../../dist/packages/platform-browser/testing"], @@ -31,7 +34,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/platform-server/testing" } diff --git a/packages/platform-server/tsconfig-build.json b/packages/platform-server/tsconfig-build.json index 9a3c1ae7d7..180dbe5df5 100644 --- a/packages/platform-server/tsconfig-build.json +++ b/packages/platform-server/tsconfig-build.json @@ -5,6 +5,7 @@ "baseUrl": ".", "rootDir": ".", "paths": { + "@angular/animations": ["../../dist/packages/animations"], "@angular/animations/browser": ["../../dist/packages/animations/browser"], "@angular/core": ["../../dist/packages/core"], "@angular/common": ["../../dist/packages/common"], @@ -26,7 +27,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "platform-server.js", "flatModuleId": "@angular/platform-server" } diff --git a/packages/platform-webworker-dynamic/tsconfig-build.json b/packages/platform-webworker-dynamic/tsconfig-build.json index 59349d77db..de65f48f3e 100644 --- a/packages/platform-webworker-dynamic/tsconfig-build.json +++ b/packages/platform-webworker-dynamic/tsconfig-build.json @@ -22,7 +22,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "platform-webworker-dynamic.js", "flatModuleId": "@angular/platform-webworker-dynamic" } diff --git a/packages/platform-webworker/tsconfig-build.json b/packages/platform-webworker/tsconfig-build.json index 1410b58754..a62277f4cd 100644 --- a/packages/platform-webworker/tsconfig-build.json +++ b/packages/platform-webworker/tsconfig-build.json @@ -19,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "platform-webworker.js", "flatModuleId": "@angular/platform-webworker" } diff --git a/packages/router/testing/tsconfig-build.json b/packages/router/testing/tsconfig-build.json index a3a8615973..423129cda9 100644 --- a/packages/router/testing/tsconfig-build.json +++ b/packages/router/testing/tsconfig-build.json @@ -20,7 +20,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "testing.js", "flatModuleId": "@angular/router/testing" } diff --git a/packages/router/tsconfig-build.json b/packages/router/tsconfig-build.json index 34529dac95..c18fc6d5c7 100644 --- a/packages/router/tsconfig-build.json +++ b/packages/router/tsconfig-build.json @@ -19,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "router.js", "flatModuleId": "@angular/router" } diff --git a/packages/router/upgrade/tsconfig-build.json b/packages/router/upgrade/tsconfig-build.json index cfab3887a9..9b59f4ff9b 100644 --- a/packages/router/upgrade/tsconfig-build.json +++ b/packages/router/upgrade/tsconfig-build.json @@ -4,6 +4,7 @@ "baseUrl": ".", "rootDir": "../", "paths": { + "@angular/common": ["../../../dist/packages/common"], "@angular/core": ["../../../dist/packages/core"], "@angular/platform-browser": ["../../../dist/packages/platform-browser"], "@angular/router": ["../../../dist/packages/router"], @@ -18,7 +19,8 @@ "angularCompilerOptions": { "annotateForClosureCompiler": true, - "strictMetadataEmit": true, + "strictMetadataEmit": false, + "skipTemplateCodegen": true, "flatModuleOutFile": "upgrade.js", "flatModuleId": "@angular/router/upgrade" } diff --git a/packages/tsc-wrapped/BUILD.bazel b/packages/tsc-wrapped/BUILD.bazel deleted file mode 100644 index f86cf576c8..0000000000 --- a/packages/tsc-wrapped/BUILD.bazel +++ /dev/null @@ -1,11 +0,0 @@ -package(default_visibility=["//visibility:public"]) -load("@build_bazel_rules_typescript//:defs.bzl", "ts_library") - -ts_library( - name = "tsc-wrapped", - srcs = glob(["**/*.ts"], exclude=[ - "test/**", - ]), - module_name = "@angular/tsc-wrapped", - tsconfig = ":tsconfig-build.json", -) diff --git a/packages/tsc-wrapped/README.md b/packages/tsc-wrapped/README.md deleted file mode 100644 index 87a7bed35a..0000000000 --- a/packages/tsc-wrapped/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# tsc-wrapped - -This package is an internal dependency used by @angular/compiler-cli. Please use that instead. - -This is a wrapper around TypeScript's `tsc` program that allows us to hook in extra extensions. -TypeScript will eventually have an extensibility model for arbitrary extensions. We don't want -to constrain their design with baggage from a legacy implementation, so this wrapper only -supports specific extensions developed by the Angular team: - -- tsickle down-levels Decorators into Annotations so they can be tree-shaken -- tsickle can also optionally produce Closure Compiler-friendly code -- ./collector.ts emits an extra `.metadata.json` file for every `.d.ts` file written, - which retains metadata about decorators that is lost in the TS emit -- @angular/compiler-cli extends this library to additionally generate template code - -## TypeScript Decorator metadata collector - -The `.d.ts` format does not preserve information about the Decorators applied to symbols. -Some tools, such as Angular template compiler, need access to statically analyzable -information about Decorators, so this library allows programs to produce a `foo.metadata.json` -to accompany a `foo.d.ts` file, and preserves the information that was lost in the declaration -emit. - -## Releasing -``` -$ $(npm bin)/tsc -p tools -$ cp tools/tsc-wrapped/package.json dist/tools/@angular/tsc-wrapped/ -$ npm login [angular] -$ npm publish dist/tools/@angular/tsc-wrapped -``` diff --git a/packages/tsc-wrapped/index.ts b/packages/tsc-wrapped/index.ts deleted file mode 100644 index 0079e4af5b..0000000000 --- a/packages/tsc-wrapped/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @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 - */ - -export {main} from './src/main'; -export * from './index_no_tsickle'; diff --git a/packages/tsc-wrapped/index_no_tsickle.ts b/packages/tsc-wrapped/index_no_tsickle.ts deleted file mode 100644 index 845e1e35c1..0000000000 --- a/packages/tsc-wrapped/index_no_tsickle.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @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 - */ - -// This index allows tsc-wrapped to be used with no dependency on tsickle. -// Short-term workaround until tsc-wrapped is removed entirely. -export {MetadataWriterHost} from './src/compiler_host'; -export {CodegenExtension, UserError, createBundleIndexHost} from './src/main_no_tsickle'; -export {default as AngularCompilerOptions} from './src/options'; - -export * from './src/bundler'; -export * from './src/cli_options'; -export * from './src/collector'; -export * from './src/index_writer'; -export * from './src/schema'; diff --git a/packages/tsc-wrapped/package.json b/packages/tsc-wrapped/package.json deleted file mode 100644 index c2e9ddec0a..0000000000 --- a/packages/tsc-wrapped/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@angular/tsc-wrapped", - "version": "0.0.0-PLACEHOLDER", - "description": "Wraps the tsc CLI, allowing extensions.", - "homepage": "https://github.com/angular/angular/blob/master/packages/tsc-wrapped", - "bugs": "https://github.com/angular/angular/issues", - "contributors": [ - "Alex Eagle ", - "Chuck Jazdzewski " - ], - "license": "MIT", - "repository": {"type":"git","url":"https://github.com/angular/angular.git"}, - "dependencies": { - "tsickle": "^0.24.0" - }, - "peerDependencies": { - "typescript": "^2.4.2" - } -} diff --git a/packages/tsc-wrapped/src/bundler.ts b/packages/tsc-wrapped/src/bundler.ts deleted file mode 100644 index e6998b2d48..0000000000 --- a/packages/tsc-wrapped/src/bundler.ts +++ /dev/null @@ -1,629 +0,0 @@ -/** - * @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 - */ -import * as path from 'path'; -import * as ts from 'typescript'; - -import {MetadataCollector} from './collector'; -import {ClassMetadata, ConstructorMetadata, FunctionMetadata, MemberMetadata, MetadataEntry, MetadataError, MetadataImportedSymbolReferenceExpression, MetadataMap, MetadataObject, MetadataSymbolicExpression, MetadataSymbolicReferenceExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, VERSION, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isInterfaceMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicExpression, isMethodMetadata} from './schema'; - - - -// The character set used to produce private names. -const PRIVATE_NAME_CHARS = 'abcdefghijklmnopqrstuvwxyz'; - -interface Symbol { - module: string; - name: string; - - // Produced by indirectly by exportAll() for symbols re-export another symbol. - exports?: Symbol; - - // Produced by indirectly by exportAll() for symbols are re-exported by another symbol. - reexportedAs?: Symbol; - - // Produced by canonicalizeSymbols() for all symbols. A symbol is private if it is not - // exported by the index. - isPrivate?: boolean; - - // Produced by canonicalizeSymbols() for all symbols. This is the one symbol that - // respresents all other symbols and is the only symbol that, among all the re-exported - // aliases, whose fields can be trusted to contain the correct information. - // For private symbols this is the declaration symbol. For public symbols this is the - // symbol that is exported. - canonicalSymbol?: Symbol; - - // Produced by canonicalizeSymbols() for all symbols. This the symbol that originally - // declared the value and should be used to fetch the value. - declaration?: Symbol; - - // A symbol is referenced if it is exported from index or referenced by the value of - // a referenced symbol's value. - referenced?: boolean; - - // A symbol is marked as a re-export the symbol was rexported from a module that is - // not part of the flat module bundle. - reexport?: boolean; - - // Only valid for referenced canonical symbols. Produces by convertSymbols(). - value?: MetadataEntry; - - // Only valid for referenced private symbols. It is the name to use to import the symbol from - // the bundle index. Produce by assignPrivateNames(); - privateName?: string; -} - -export interface BundleEntries { [name: string]: MetadataEntry; } - -export interface BundlePrivateEntry { - privateName: string; - name: string; - module: string; -} - -export interface BundledModule { - metadata: ModuleMetadata; - privates: BundlePrivateEntry[]; -} - -export interface MetadataBundlerHost { - getMetadataFor(moduleName: string): ModuleMetadata|undefined; -} - -type StaticsMetadata = { - [name: string]: MetadataValue | FunctionMetadata; -}; - -export class MetadataBundler { - private symbolMap = new Map(); - private metadataCache = new Map(); - private exports = new Map(); - private rootModule: string; - private exported: Set; - - constructor( - private root: string, private importAs: string|undefined, private host: MetadataBundlerHost) { - this.rootModule = `./${path.basename(root)}`; - } - - getMetadataBundle(): BundledModule { - // Export the root module. This also collects the transitive closure of all values referenced by - // the exports. - const exportedSymbols = this.exportAll(this.rootModule); - this.canonicalizeSymbols(exportedSymbols); - // TODO: exports? e.g. a module re-exports a symbol from another bundle - const metadata = this.getEntries(exportedSymbols); - const privates = Array.from(this.symbolMap.values()) - .filter(s => s.referenced && s.isPrivate) - .map(s => ({ - privateName: s.privateName !, - name: s.declaration !.name, - module: s.declaration !.module - })); - const origins = Array.from(this.symbolMap.values()) - .filter(s => s.referenced && !s.reexport) - .reduce<{[name: string]: string}>((p, s) => { - p[s.isPrivate ? s.privateName ! : s.name] = s.declaration !.module; - return p; - }, {}); - const exports = this.getReExports(exportedSymbols); - return { - metadata: { - __symbolic: 'module', - version: VERSION, - exports: exports.length ? exports : undefined, metadata, origins, - importAs: this.importAs ! - }, - privates - }; - } - - static resolveModule(importName: string, from: string): string { - return resolveModule(importName, from); - } - - private getMetadata(moduleName: string): ModuleMetadata|undefined { - let result = this.metadataCache.get(moduleName); - if (!result) { - if (moduleName.startsWith('.')) { - const fullModuleName = resolveModule(moduleName, this.root); - result = this.host.getMetadataFor(fullModuleName); - } - this.metadataCache.set(moduleName, result); - } - return result; - } - - private exportAll(moduleName: string): Symbol[] { - const module = this.getMetadata(moduleName); - let result = this.exports.get(moduleName); - - if (result) { - return result; - } - - result = []; - - const exportSymbol = (exportedSymbol: Symbol, exportAs: string) => { - const symbol = this.symbolOf(moduleName, exportAs); - result !.push(symbol); - exportedSymbol.reexportedAs = symbol; - symbol.exports = exportedSymbol; - }; - - // Export all the symbols defined in this module. - if (module && module.metadata) { - for (let key in module.metadata) { - const data = module.metadata[key]; - if (isMetadataImportedSymbolReferenceExpression(data)) { - // This is a re-export of an imported symbol. Record this as a re-export. - const exportFrom = resolveModule(data.module, moduleName); - this.exportAll(exportFrom); - const symbol = this.symbolOf(exportFrom, data.name); - exportSymbol(symbol, key); - } else { - // Record that this symbol is exported by this module. - result.push(this.symbolOf(moduleName, key)); - } - } - } - - // Export all the re-exports from this module - if (module && module.exports) { - for (const exportDeclaration of module.exports) { - const exportFrom = resolveModule(exportDeclaration.from, moduleName); - // Record all the exports from the module even if we don't use it directly. - const exportedSymbols = this.exportAll(exportFrom); - if (exportDeclaration.export) { - // Re-export all the named exports from a module. - for (const exportItem of exportDeclaration.export) { - const name = typeof exportItem == 'string' ? exportItem : exportItem.name; - const exportAs = typeof exportItem == 'string' ? exportItem : exportItem.as; - const symbol = this.symbolOf(exportFrom, name); - if (exportedSymbols && exportedSymbols.length == 1 && exportedSymbols[0].reexport && - exportedSymbols[0].name == '*') { - // This is a named export from a module we have no metadata about. Record the named - // export as a re-export. - symbol.reexport = true; - } - exportSymbol(this.symbolOf(exportFrom, name), exportAs); - } - } else { - // Re-export all the symbols from the module - const exportedSymbols = this.exportAll(exportFrom); - for (const exportedSymbol of exportedSymbols) { - const name = exportedSymbol.name; - exportSymbol(exportedSymbol, name); - } - } - } - } - - if (!module) { - // If no metadata is found for this import then it is considered external to the - // library and should be recorded as a re-export in the final metadata if it is - // eventually re-exported. - const symbol = this.symbolOf(moduleName, '*'); - symbol.reexport = true; - result.push(symbol); - } - this.exports.set(moduleName, result); - - return result; - } - - /** - * Fill in the canonicalSymbol which is the symbol that should be imported by factories. - * The canonical symbol is the one exported by the index file for the bundle or definition - * symbol for private symbols that are not exported by bundle index. - */ - private canonicalizeSymbols(exportedSymbols: Symbol[]) { - const symbols = Array.from(this.symbolMap.values()); - this.exported = new Set(exportedSymbols); - symbols.forEach(this.canonicalizeSymbol, this); - } - - private canonicalizeSymbol(symbol: Symbol) { - const rootExport = getRootExport(symbol); - const declaration = getSymbolDeclaration(symbol); - const isPrivate = !this.exported.has(rootExport); - const canonicalSymbol = isPrivate ? declaration : rootExport; - symbol.isPrivate = isPrivate; - symbol.declaration = declaration; - symbol.canonicalSymbol = canonicalSymbol; - symbol.reexport = declaration.reexport; - } - - private getEntries(exportedSymbols: Symbol[]): BundleEntries { - const result: BundleEntries = {}; - - const exportedNames = new Set(exportedSymbols.map(s => s.name)); - let privateName = 0; - - function newPrivateName(): string { - while (true) { - let digits: string[] = []; - let index = privateName++; - let base = PRIVATE_NAME_CHARS; - while (!digits.length || index > 0) { - digits.unshift(base[index % base.length]); - index = Math.floor(index / base.length); - } - digits.unshift('\u0275'); - const result = digits.join(''); - if (!exportedNames.has(result)) return result; - } - } - - exportedSymbols.forEach(symbol => this.convertSymbol(symbol)); - - const symbolsMap = new Map(); - Array.from(this.symbolMap.values()).forEach(symbol => { - if (symbol.referenced && !symbol.reexport) { - let name = symbol.name; - const identifier = `${symbol.declaration!.module}:${symbol.declaration !.name}`; - if (symbol.isPrivate && !symbol.privateName) { - name = newPrivateName(); - symbol.privateName = name; - } - if (symbolsMap.has(identifier)) { - const names = symbolsMap.get(identifier); - names !.push(name); - } else { - symbolsMap.set(identifier, [name]); - } - result[name] = symbol.value !; - } - }); - - // check for duplicated entries - symbolsMap.forEach((names: string[], identifier: string) => { - if (names.length > 1) { - const [module, declaredName] = identifier.split(':'); - // prefer the export that uses the declared name (if any) - let reference = names.indexOf(declaredName); - if (reference === -1) { - reference = 0; - } - - // keep one entry and replace the others by references - names.forEach((name: string, i: number) => { - if (i !== reference) { - result[name] = {__symbolic: 'reference', name: names[reference]}; - } - }); - } - }); - - return result; - } - - private getReExports(exportedSymbols: Symbol[]): ModuleExportMetadata[] { - type ExportClause = {name: string, as: string}[]; - const modules = new Map(); - const exportAlls = new Set(); - for (const symbol of exportedSymbols) { - if (symbol.reexport) { - // symbol.declaration is guarenteed to be defined during the phase this method is called. - const declaration = symbol.declaration !; - const module = declaration.module; - if (declaration !.name == '*') { - // Reexport all the symbols. - exportAlls.add(declaration.module); - } else { - // Re-export the symbol as the exported name. - let entry = modules.get(module); - if (!entry) { - entry = []; - modules.set(module, entry); - } - const as = symbol.name; - const name = declaration.name; - entry.push({name, as}); - } - } - } - return [ - ...Array.from(exportAlls.values()).map(from => ({from})), - ...Array.from(modules.entries()).map(([from, exports]) => ({export: exports, from})) - ]; - } - - private convertSymbol(symbol: Symbol) { - // canonicalSymbol is ensured to be defined before this is called. - const canonicalSymbol = symbol.canonicalSymbol !; - - if (!canonicalSymbol.referenced) { - canonicalSymbol.referenced = true; - // declaration is ensured to be definded before this method is called. - const declaration = canonicalSymbol.declaration !; - const module = this.getMetadata(declaration.module); - if (module) { - const value = module.metadata[declaration.name]; - if (value && !declaration.name.startsWith('___')) { - canonicalSymbol.value = this.convertEntry(declaration.module, value); - } - } - } - } - - private convertEntry(moduleName: string, value: MetadataEntry): MetadataEntry { - if (isClassMetadata(value)) { - return this.convertClass(moduleName, value); - } - if (isFunctionMetadata(value)) { - return this.convertFunction(moduleName, value); - } - if (isInterfaceMetadata(value)) { - return value; - } - return this.convertValue(moduleName, value); - } - - private convertClass(moduleName: string, value: ClassMetadata): ClassMetadata { - return { - __symbolic: 'class', - arity: value.arity, - extends: this.convertExpression(moduleName, value.extends) !, - decorators: - value.decorators && value.decorators.map(d => this.convertExpression(moduleName, d) !), - members: this.convertMembers(moduleName, value.members !), - statics: value.statics && this.convertStatics(moduleName, value.statics) - }; - } - - private convertMembers(moduleName: string, members: MetadataMap): MetadataMap { - const result: MetadataMap = {}; - for (const name in members) { - const value = members[name]; - result[name] = value.map(v => this.convertMember(moduleName, v)); - } - return result; - } - - private convertMember(moduleName: string, member: MemberMetadata) { - const result: MemberMetadata = {__symbolic: member.__symbolic}; - result.decorators = - member.decorators && member.decorators.map(d => this.convertExpression(moduleName, d) !); - if (isMethodMetadata(member)) { - (result as MethodMetadata).parameterDecorators = member.parameterDecorators && - member.parameterDecorators.map( - d => d && d.map(p => this.convertExpression(moduleName, p) !)); - if (isConstructorMetadata(member)) { - if (member.parameters) { - (result as ConstructorMetadata).parameters = - member.parameters.map(p => this.convertExpression(moduleName, p)); - } - } - } - return result; - } - - private convertStatics(moduleName: string, statics: StaticsMetadata): StaticsMetadata { - let result: StaticsMetadata = {}; - for (const key in statics) { - const value = statics[key]; - result[key] = isFunctionMetadata(value) ? this.convertFunction(moduleName, value) : value; - } - return result; - } - - private convertFunction(moduleName: string, value: FunctionMetadata): FunctionMetadata { - return { - __symbolic: 'function', - parameters: value.parameters, - defaults: value.defaults && value.defaults.map(v => this.convertValue(moduleName, v)), - value: this.convertValue(moduleName, value.value) - }; - } - - private convertValue(moduleName: string, value: MetadataValue): MetadataValue { - if (isPrimitive(value)) { - return value; - } - if (isMetadataError(value)) { - return this.convertError(moduleName, value); - } - if (isMetadataSymbolicExpression(value)) { - return this.convertExpression(moduleName, value) !; - } - if (Array.isArray(value)) { - return value.map(v => this.convertValue(moduleName, v)); - } - - // Otherwise it is a metadata object. - const object = value as MetadataObject; - const result: MetadataObject = {}; - for (const key in object) { - result[key] = this.convertValue(moduleName, object[key]); - } - return result; - } - - private convertExpression( - moduleName: string, value: MetadataSymbolicExpression|MetadataError|null| - undefined): MetadataSymbolicExpression|MetadataError|undefined|null { - if (value) { - switch (value.__symbolic) { - case 'error': - return this.convertError(moduleName, value as MetadataError); - case 'reference': - return this.convertReference(moduleName, value as MetadataSymbolicReferenceExpression); - default: - return this.convertExpressionNode(moduleName, value); - } - } - return value; - } - - private convertError(module: string, value: MetadataError): MetadataError { - return { - __symbolic: 'error', - message: value.message, - line: value.line, - character: value.character, - context: value.context, module - }; - } - - private convertReference(moduleName: string, value: MetadataSymbolicReferenceExpression): - MetadataSymbolicReferenceExpression|MetadataError|undefined { - const createReference = (symbol: Symbol): MetadataSymbolicReferenceExpression => { - const declaration = symbol.declaration !; - if (declaration.module.startsWith('.')) { - // Reference to a symbol defined in the module. Ensure it is converted then return a - // references to the final symbol. - this.convertSymbol(symbol); - return { - __symbolic: 'reference', - get name() { - // Resolved lazily because private names are assigned late. - const canonicalSymbol = symbol.canonicalSymbol !; - if (canonicalSymbol.isPrivate == null) { - throw Error('Invalid state: isPrivate was not initialized'); - } - return canonicalSymbol.isPrivate ? canonicalSymbol.privateName ! : canonicalSymbol.name; - } - }; - } else { - // The symbol was a re-exported symbol from another module. Return a reference to the - // original imported symbol. - return {__symbolic: 'reference', name: declaration.name, module: declaration.module}; - } - }; - - if (isMetadataGlobalReferenceExpression(value)) { - const metadata = this.getMetadata(moduleName); - if (metadata && metadata.metadata && metadata.metadata[value.name]) { - // Reference to a symbol defined in the module - return createReference(this.canonicalSymbolOf(moduleName, value.name)); - } - - // If a reference has arguments, the arguments need to be converted. - if (value.arguments) { - return { - __symbolic: 'reference', - name: value.name, - arguments: value.arguments.map(a => this.convertValue(moduleName, a)) - }; - } - - // Global references without arguments (such as to Math or JSON) are unmodified. - return value; - } - - if (isMetadataImportedSymbolReferenceExpression(value)) { - // References to imported symbols are separated into two, references to bundled modules and - // references to modules external to the bundle. If the module reference is relative it is - // assumed to be in the bundle. If it is Global it is assumed to be outside the bundle. - // References to symbols outside the bundle are left unmodified. References to symbol inside - // the bundle need to be converted to a bundle import reference reachable from the bundle - // index. - - if (value.module.startsWith('.')) { - // Reference is to a symbol defined inside the module. Convert the reference to a reference - // to the canonical symbol. - const referencedModule = resolveModule(value.module, moduleName); - const referencedName = value.name; - return createReference(this.canonicalSymbolOf(referencedModule, referencedName)); - } - - // Value is a reference to a symbol defined outside the module. - if (value.arguments) { - // If a reference has arguments the arguments need to be converted. - return { - __symbolic: 'reference', - name: value.name, - module: value.module, - arguments: value.arguments.map(a => this.convertValue(moduleName, a)) - }; - } - return value; - } - - if (isMetadataModuleReferenceExpression(value)) { - // Cannot support references to bundled modules as the internal modules of a bundle are erased - // by the bundler. - if (value.module.startsWith('.')) { - return { - __symbolic: 'error', - message: 'Unsupported bundled module reference', - context: {module: value.module} - }; - } - - // References to unbundled modules are unmodified. - return value; - } - } - - private convertExpressionNode(moduleName: string, value: MetadataSymbolicExpression): - MetadataSymbolicExpression { - const result: MetadataSymbolicExpression = {__symbolic: value.__symbolic}; - for (const key in value) { - (result as any)[key] = this.convertValue(moduleName, (value as any)[key]); - } - return result; - } - - private symbolOf(module: string, name: string): Symbol { - const symbolKey = `${module}:${name}`; - let symbol = this.symbolMap.get(symbolKey); - if (!symbol) { - symbol = {module, name}; - this.symbolMap.set(symbolKey, symbol); - } - return symbol; - } - - private canonicalSymbolOf(module: string, name: string): Symbol { - // Ensure the module has been seen. - this.exportAll(module); - const symbol = this.symbolOf(module, name); - if (!symbol.canonicalSymbol) { - this.canonicalizeSymbol(symbol); - } - return symbol; - } -} - -export class CompilerHostAdapter implements MetadataBundlerHost { - private collector = new MetadataCollector(); - - constructor(private host: ts.CompilerHost) {} - - getMetadataFor(fileName: string): ModuleMetadata|undefined { - const sourceFile = this.host.getSourceFile(fileName + '.ts', ts.ScriptTarget.Latest); - return this.collector.getMetadata(sourceFile); - } -} - -function resolveModule(importName: string, from: string): string { - if (importName.startsWith('.') && from) { - let normalPath = path.normalize(path.join(path.dirname(from), importName)); - if (!normalPath.startsWith('.') && from.startsWith('.')) { - // path.normalize() preserves leading '../' but not './'. This adds it back. - normalPath = `.${path.sep}${normalPath}`; - } - // Replace windows path delimiters with forward-slashes. Otherwise the paths are not - // TypeScript compatible when building the bundle. - return normalPath.replace(/\\/g, '/'); - } - return importName; -} - -function isPrimitive(o: any): o is boolean|string|number { - return o === null || (typeof o !== 'function' && typeof o !== 'object'); -} - -function getRootExport(symbol: Symbol): Symbol { - return symbol.reexportedAs ? getRootExport(symbol.reexportedAs) : symbol; -} - -function getSymbolDeclaration(symbol: Symbol): Symbol { - return symbol.exports ? getSymbolDeclaration(symbol.exports) : symbol; -} diff --git a/packages/tsc-wrapped/src/cli_options.ts b/packages/tsc-wrapped/src/cli_options.ts deleted file mode 100644 index 5755f8665e..0000000000 --- a/packages/tsc-wrapped/src/cli_options.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @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 - */ -export class CliOptions { - public basePath: string|null; - constructor({basePath = null}: {basePath?: string | null}) { this.basePath = basePath; } -} - -export class I18nExtractionCliOptions extends CliOptions { - i18nFormat: string|null; - locale: string|null; - outFile: string|null; - - constructor({i18nFormat = null, locale = null, outFile = null}: { - i18nFormat?: string, - locale?: string, - outFile?: string, - }) { - super({}); - this.i18nFormat = i18nFormat; - this.locale = locale; - this.outFile = outFile; - } -} - -export class NgcCliOptions extends CliOptions { - public i18nFormat: string|null; - public i18nFile: string|null; - public locale: string|null; - public missingTranslation: string|null; - - constructor({i18nFormat = null, i18nFile = null, locale = null, missingTranslation = null, - basePath = null}: { - i18nFormat?: string | null, - i18nFile?: string|null, - locale?: string|null, - missingTranslation?: string|null, - basePath?: string|null - }) { - super({basePath: basePath}); - this.i18nFormat = i18nFormat; - this.i18nFile = i18nFile; - this.locale = locale; - this.missingTranslation = missingTranslation; - } -} diff --git a/packages/tsc-wrapped/src/collector.ts b/packages/tsc-wrapped/src/collector.ts deleted file mode 100644 index b9b5f3a45b..0000000000 --- a/packages/tsc-wrapped/src/collector.ts +++ /dev/null @@ -1,774 +0,0 @@ -/** - * @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 - */ - -import * as ts from 'typescript'; - -import {Evaluator, errorSymbol} from './evaluator'; -import {ClassMetadata, ConstructorMetadata, FunctionMetadata, InterfaceMetadata, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, VERSION, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema'; -import {Symbols} from './symbols'; - -// In TypeScript 2.1 these flags moved -// These helpers work for both 2.0 and 2.1. -const isExport = (ts as any).ModifierFlags ? - ((node: ts.Node) => - !!((ts as any).getCombinedModifierFlags(node) & (ts as any).ModifierFlags.Export)) : - ((node: ts.Node) => !!((node.flags & (ts as any).NodeFlags.Export))); -const isStatic = (ts as any).ModifierFlags ? - ((node: ts.Node) => - !!((ts as any).getCombinedModifierFlags(node) & (ts as any).ModifierFlags.Static)) : - ((node: ts.Node) => !!((node.flags & (ts as any).NodeFlags.Static))); - -/** - * A set of collector options to use when collecting metadata. - */ -export interface CollectorOptions { - /** - * Version of the metadata to collect. - */ - version?: number; - - /** - * Collect a hidden field "$quoted$" in objects literals that record when the key was quoted in - * the source. - */ - quotedNames?: boolean; - - /** - * Do not simplify invalid expressions. - */ - verboseInvalidExpression?: boolean; - - /** - * An expression substitution callback. - */ - substituteExpression?: (value: MetadataValue, node: ts.Node) => MetadataValue; -} - -/** - * Collect decorator metadata from a TypeScript module. - */ -export class MetadataCollector { - constructor(private options: CollectorOptions = {}) {} - - /** - * Returns a JSON.stringify friendly form describing the decorators of the exported classes from - * the source file that is expected to correspond to a module. - */ - public getMetadata( - sourceFile: ts.SourceFile, strict: boolean = false, - substituteExpression?: (value: MetadataValue, node: ts.Node) => MetadataValue): ModuleMetadata - |undefined { - const locals = new Symbols(sourceFile); - const nodeMap = - new Map(); - const composedSubstituter = substituteExpression && this.options.substituteExpression ? - (value: MetadataValue, node: ts.Node) => - this.options.substituteExpression !(substituteExpression(value, node), node) : - substituteExpression; - const evaluatorOptions = substituteExpression ? - {...this.options, substituteExpression: composedSubstituter} : - this.options; - let metadata: {[name: string]: MetadataValue | ClassMetadata | FunctionMetadata}|undefined; - const evaluator = new Evaluator(locals, nodeMap, evaluatorOptions, (name, value) => { - if (!metadata) metadata = {}; - metadata[name] = value; - }); - let exports: ModuleExportMetadata[]|undefined = undefined; - - function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression { - return evaluator.evaluateNode(decoratorNode.expression); - } - - function recordEntry(entry: T, node: ts.Node): T { - nodeMap.set(entry, node); - return entry; - } - - function errorSym( - message: string, node?: ts.Node, context?: {[name: string]: string}): MetadataError { - return errorSymbol(message, node, context, sourceFile); - } - - function maybeGetSimpleFunction( - functionDeclaration: ts.FunctionDeclaration | - ts.MethodDeclaration): {func: FunctionMetadata, name: string}|undefined { - if (functionDeclaration.name && functionDeclaration.name.kind == ts.SyntaxKind.Identifier) { - const nameNode = functionDeclaration.name; - const functionName = nameNode.text; - const functionBody = functionDeclaration.body; - if (functionBody && functionBody.statements.length == 1) { - const statement = functionBody.statements[0]; - if (statement.kind === ts.SyntaxKind.ReturnStatement) { - const returnStatement = statement; - if (returnStatement.expression) { - const func: FunctionMetadata = { - __symbolic: 'function', - parameters: namesOf(functionDeclaration.parameters), - value: evaluator.evaluateNode(returnStatement.expression) - }; - if (functionDeclaration.parameters.some(p => p.initializer != null)) { - func.defaults = functionDeclaration.parameters.map( - p => p.initializer && evaluator.evaluateNode(p.initializer)); - } - return recordEntry({func, name: functionName}, functionDeclaration); - } - } - } - } - } - - function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata { - const result: ClassMetadata = {__symbolic: 'class'}; - - function getDecorators(decorators: ts.Decorator[] | undefined): MetadataSymbolicExpression[]| - undefined { - if (decorators && decorators.length) - return decorators.map(decorator => objFromDecorator(decorator)); - return undefined; - } - - function referenceFrom(node: ts.Node): MetadataSymbolicReferenceExpression|MetadataError| - MetadataSymbolicSelectExpression { - const result = evaluator.evaluateNode(node); - if (isMetadataError(result) || isMetadataSymbolicReferenceExpression(result) || - isMetadataSymbolicSelectExpression(result)) { - return result; - } else { - return errorSym('Symbol reference expected', node); - } - } - - // Add class parents - if (classDeclaration.heritageClauses) { - classDeclaration.heritageClauses.forEach((hc) => { - if (hc.token === ts.SyntaxKind.ExtendsKeyword && hc.types) { - hc.types.forEach(type => result.extends = referenceFrom(type.expression)); - } - }); - } - - // Add arity if the type is generic - const typeParameters = classDeclaration.typeParameters; - if (typeParameters && typeParameters.length) { - result.arity = typeParameters.length; - } - - // Add class decorators - if (classDeclaration.decorators) { - result.decorators = getDecorators(classDeclaration.decorators); - } - - // member decorators - let members: MetadataMap|null = null; - function recordMember(name: string, metadata: MemberMetadata) { - if (!members) members = {}; - const data = members.hasOwnProperty(name) ? members[name] : []; - data.push(metadata); - members[name] = data; - } - - // static member - let statics: {[name: string]: MetadataValue | FunctionMetadata}|null = null; - function recordStaticMember(name: string, value: MetadataValue | FunctionMetadata) { - if (!statics) statics = {}; - statics[name] = value; - } - - for (const member of classDeclaration.members) { - let isConstructor = false; - switch (member.kind) { - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.MethodDeclaration: - isConstructor = member.kind === ts.SyntaxKind.Constructor; - const method = member; - if (isStatic(method)) { - const maybeFunc = maybeGetSimpleFunction(method); - if (maybeFunc) { - recordStaticMember(maybeFunc.name, maybeFunc.func); - } - continue; - } - const methodDecorators = getDecorators(method.decorators); - const parameters = method.parameters; - const parameterDecoratorData: - ((MetadataSymbolicExpression | MetadataError)[] | undefined)[] = []; - const parametersData: - (MetadataSymbolicReferenceExpression | MetadataError | - MetadataSymbolicSelectExpression | null)[] = []; - let hasDecoratorData: boolean = false; - let hasParameterData: boolean = false; - for (const parameter of parameters) { - const parameterData = getDecorators(parameter.decorators); - parameterDecoratorData.push(parameterData); - hasDecoratorData = hasDecoratorData || !!parameterData; - if (isConstructor) { - if (parameter.type) { - parametersData.push(referenceFrom(parameter.type)); - } else { - parametersData.push(null); - } - hasParameterData = true; - } - } - const data: MethodMetadata = {__symbolic: isConstructor ? 'constructor' : 'method'}; - const name = isConstructor ? '__ctor__' : evaluator.nameOf(member.name); - if (methodDecorators) { - data.decorators = methodDecorators; - } - if (hasDecoratorData) { - data.parameterDecorators = parameterDecoratorData; - } - if (hasParameterData) { - (data).parameters = parametersData; - } - if (!isMetadataError(name)) { - recordMember(name, data); - } - break; - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - const property = member; - if (isStatic(property)) { - const name = evaluator.nameOf(property.name); - if (!isMetadataError(name)) { - if (property.initializer) { - const value = evaluator.evaluateNode(property.initializer); - recordStaticMember(name, value); - } else { - recordStaticMember(name, errorSym('Variable not initialized', property.name)); - } - } - } - const propertyDecorators = getDecorators(property.decorators); - if (propertyDecorators) { - const name = evaluator.nameOf(property.name); - if (!isMetadataError(name)) { - recordMember(name, {__symbolic: 'property', decorators: propertyDecorators}); - } - } - break; - } - } - if (members) { - result.members = members; - } - if (statics) { - result.statics = statics; - } - - return recordEntry(result, classDeclaration); - } - - // Collect all exported symbols from an exports clause. - const exportMap = new Map(); - ts.forEachChild(sourceFile, node => { - switch (node.kind) { - case ts.SyntaxKind.ExportDeclaration: - const exportDeclaration = node; - const {moduleSpecifier, exportClause} = exportDeclaration; - - if (!moduleSpecifier) { - // If there is a module specifier there is also an exportClause - exportClause !.elements.forEach(spec => { - const exportedAs = spec.name.text; - const name = (spec.propertyName || spec.name).text; - exportMap.set(name, exportedAs); - }); - } - } - }); - - const isExportedIdentifier = (identifier?: ts.Identifier) => - identifier && exportMap.has(identifier.text); - const isExported = - (node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration | - ts.InterfaceDeclaration | ts.EnumDeclaration) => - isExport(node) || isExportedIdentifier(node.name); - const exportedIdentifierName = (identifier?: ts.Identifier) => - identifier && (exportMap.get(identifier.text) || identifier.text); - const exportedName = - (node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration | - ts.TypeAliasDeclaration | ts.EnumDeclaration) => exportedIdentifierName(node.name); - - - // Predeclare classes and functions - ts.forEachChild(sourceFile, node => { - switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - const classDeclaration = node; - if (classDeclaration.name) { - const className = classDeclaration.name.text; - if (isExported(classDeclaration)) { - locals.define( - className, {__symbolic: 'reference', name: exportedName(classDeclaration)}); - } else { - locals.define( - className, errorSym('Reference to non-exported class', node, {className})); - } - } - break; - - case ts.SyntaxKind.InterfaceDeclaration: - const interfaceDeclaration = node; - if (interfaceDeclaration.name) { - const interfaceName = interfaceDeclaration.name.text; - // All references to interfaces should be converted to references to `any`. - locals.define(interfaceName, {__symbolic: 'reference', name: 'any'}); - } - break; - - case ts.SyntaxKind.FunctionDeclaration: - const functionDeclaration = node; - if (!isExported(functionDeclaration)) { - // Report references to this function as an error. - const nameNode = functionDeclaration.name; - if (nameNode && nameNode.text) { - locals.define( - nameNode.text, - errorSym( - 'Reference to a non-exported function', nameNode, {name: nameNode.text})); - } - } - break; - } - }); - - ts.forEachChild(sourceFile, node => { - switch (node.kind) { - case ts.SyntaxKind.ExportDeclaration: - // Record export declarations - const exportDeclaration = node; - const {moduleSpecifier, exportClause} = exportDeclaration; - - if (!moduleSpecifier) { - // no module specifier -> export {propName as name}; - if (exportClause) { - exportClause.elements.forEach(spec => { - const name = spec.name.text; - // If the symbol was not already exported, export a reference since it is a - // reference to an import - if (!metadata || !metadata[name]) { - const propNode = spec.propertyName || spec.name; - const value: MetadataValue = evaluator.evaluateNode(propNode); - if (!metadata) metadata = {}; - metadata[name] = recordEntry(value, node); - } - }); - } - } - - if (moduleSpecifier && moduleSpecifier.kind == ts.SyntaxKind.StringLiteral) { - // Ignore exports that don't have string literals as exports. - // This is allowed by the syntax but will be flagged as an error by the type checker. - const from = (moduleSpecifier).text; - const moduleExport: ModuleExportMetadata = {from}; - if (exportClause) { - moduleExport.export = exportClause.elements.map( - spec => spec.propertyName ? {name: spec.propertyName.text, as: spec.name.text} : - spec.name.text); - } - if (!exports) exports = []; - exports.push(moduleExport); - } - break; - case ts.SyntaxKind.ClassDeclaration: - const classDeclaration = node; - if (classDeclaration.name) { - if (isExported(classDeclaration)) { - const name = exportedName(classDeclaration); - if (name) { - if (!metadata) metadata = {}; - metadata[name] = classMetadataOf(classDeclaration); - } - } - } - // Otherwise don't record metadata for the class. - break; - - case ts.SyntaxKind.TypeAliasDeclaration: - const typeDeclaration = node; - if (typeDeclaration.name && isExported(typeDeclaration)) { - const name = exportedName(typeDeclaration); - if (name) { - if (!metadata) metadata = {}; - metadata[name] = {__symbolic: 'interface'}; - } - } - break; - - case ts.SyntaxKind.InterfaceDeclaration: - const interfaceDeclaration = node; - if (interfaceDeclaration.name && isExported(interfaceDeclaration)) { - const name = exportedName(interfaceDeclaration); - if (name) { - if (!metadata) metadata = {}; - metadata[name] = {__symbolic: 'interface'}; - } - } - break; - - case ts.SyntaxKind.FunctionDeclaration: - // Record functions that return a single value. Record the parameter - // names substitution will be performed by the StaticReflector. - const functionDeclaration = node; - if (isExported(functionDeclaration) && functionDeclaration.name) { - const name = exportedName(functionDeclaration); - const maybeFunc = maybeGetSimpleFunction(functionDeclaration); - if (name) { - if (!metadata) metadata = {}; - metadata[name] = - maybeFunc ? recordEntry(maybeFunc.func, node) : {__symbolic: 'function'}; - } - } - break; - - case ts.SyntaxKind.EnumDeclaration: - const enumDeclaration = node; - if (isExported(enumDeclaration)) { - const enumValueHolder: {[name: string]: MetadataValue} = {}; - const enumName = exportedName(enumDeclaration); - let nextDefaultValue: MetadataValue = 0; - let writtenMembers = 0; - for (const member of enumDeclaration.members) { - let enumValue: MetadataValue; - if (!member.initializer) { - enumValue = nextDefaultValue; - } else { - enumValue = evaluator.evaluateNode(member.initializer); - } - let name: string|undefined = undefined; - if (member.name.kind == ts.SyntaxKind.Identifier) { - const identifier = member.name; - name = identifier.text; - enumValueHolder[name] = enumValue; - writtenMembers++; - } - if (typeof enumValue === 'number') { - nextDefaultValue = enumValue + 1; - } else if (name) { - nextDefaultValue = { - __symbolic: 'binary', - operator: '+', - left: { - __symbolic: 'select', - expression: recordEntry({__symbolic: 'reference', name: enumName}, node), name - } - }; - } else { - nextDefaultValue = - recordEntry(errorSym('Unsuppported enum member name', member.name), node); - } - } - if (writtenMembers) { - if (enumName) { - if (!metadata) metadata = {}; - metadata[enumName] = recordEntry(enumValueHolder, node); - } - } - } - break; - - case ts.SyntaxKind.VariableStatement: - const variableStatement = node; - for (const variableDeclaration of variableStatement.declarationList.declarations) { - if (variableDeclaration.name.kind == ts.SyntaxKind.Identifier) { - const nameNode = variableDeclaration.name; - let varValue: MetadataValue; - if (variableDeclaration.initializer) { - varValue = evaluator.evaluateNode(variableDeclaration.initializer); - } else { - varValue = recordEntry(errorSym('Variable not initialized', nameNode), nameNode); - } - let exported = false; - if (isExport(variableStatement) || isExport(variableDeclaration) || - isExportedIdentifier(nameNode)) { - const name = exportedIdentifierName(nameNode); - if (name) { - if (!metadata) metadata = {}; - metadata[name] = recordEntry(varValue, node); - } - exported = true; - } - if (typeof varValue == 'string' || typeof varValue == 'number' || - typeof varValue == 'boolean') { - locals.define(nameNode.text, varValue); - if (exported) { - locals.defineReference( - nameNode.text, {__symbolic: 'reference', name: nameNode.text}); - } - } else if (!exported) { - if (varValue && !isMetadataError(varValue)) { - locals.define(nameNode.text, recordEntry(varValue, node)); - } else { - locals.define( - nameNode.text, - recordEntry( - errorSym('Reference to a local symbol', nameNode, {name: nameNode.text}), - node)); - } - } - } else { - // Destructuring (or binding) declarations are not supported, - // var {[, ]+} = ; - // or - // var [[, ; - // are not supported. - const report: (nameNode: ts.Node) => void = (nameNode: ts.Node) => { - switch (nameNode.kind) { - case ts.SyntaxKind.Identifier: - const name = nameNode; - const varValue = errorSym('Destructuring not supported', name); - locals.define(name.text, varValue); - if (isExport(node)) { - if (!metadata) metadata = {}; - metadata[name.text] = varValue; - } - break; - case ts.SyntaxKind.BindingElement: - const bindingElement = nameNode; - report(bindingElement.name); - break; - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - const bindings = nameNode; - (bindings as any).elements.forEach(report); - break; - } - }; - report(variableDeclaration.name); - } - } - break; - } - }); - - if (metadata || exports) { - if (!metadata) - metadata = {}; - else if (strict) { - validateMetadata(sourceFile, nodeMap, metadata); - } - const result: ModuleMetadata = { - __symbolic: 'module', - version: this.options.version || VERSION, metadata - }; - if (exports) result.exports = exports; - return result; - } - } -} - -// This will throw if the metadata entry given contains an error node. -function validateMetadata( - sourceFile: ts.SourceFile, nodeMap: Map, - metadata: {[name: string]: MetadataEntry}) { - let locals: Set = new Set(['Array', 'Object', 'Set', 'Map', 'string', 'number', 'any']); - - function validateExpression( - expression: MetadataValue | MetadataSymbolicExpression | MetadataError) { - if (!expression) { - return; - } else if (Array.isArray(expression)) { - expression.forEach(validateExpression); - } else if (typeof expression === 'object' && !expression.hasOwnProperty('__symbolic')) { - Object.getOwnPropertyNames(expression).forEach(v => validateExpression((expression)[v])); - } else if (isMetadataError(expression)) { - reportError(expression); - } else if (isMetadataGlobalReferenceExpression(expression)) { - if (!locals.has(expression.name)) { - const reference = metadata[expression.name]; - if (reference) { - validateExpression(reference); - } - } - } else if (isFunctionMetadata(expression)) { - validateFunction(expression); - } else if (isMetadataSymbolicExpression(expression)) { - switch (expression.__symbolic) { - case 'binary': - const binaryExpression = expression; - validateExpression(binaryExpression.left); - validateExpression(binaryExpression.right); - break; - case 'call': - case 'new': - const callExpression = expression; - validateExpression(callExpression.expression); - if (callExpression.arguments) callExpression.arguments.forEach(validateExpression); - break; - case 'index': - const indexExpression = expression; - validateExpression(indexExpression.expression); - validateExpression(indexExpression.index); - break; - case 'pre': - const prefixExpression = expression; - validateExpression(prefixExpression.operand); - break; - case 'select': - const selectExpression = expression; - validateExpression(selectExpression.expression); - break; - case 'spread': - const spreadExpression = expression; - validateExpression(spreadExpression.expression); - break; - case 'if': - const ifExpression = expression; - validateExpression(ifExpression.condition); - validateExpression(ifExpression.elseExpression); - validateExpression(ifExpression.thenExpression); - break; - } - } - } - - function validateMember(classData: ClassMetadata, member: MemberMetadata) { - if (member.decorators) { - member.decorators.forEach(validateExpression); - } - if (isMethodMetadata(member) && member.parameterDecorators) { - member.parameterDecorators.forEach(validateExpression); - } - // Only validate parameters of classes for which we know that are used with our DI - if (classData.decorators && isConstructorMetadata(member) && member.parameters) { - member.parameters.forEach(validateExpression); - } - } - - function validateClass(classData: ClassMetadata) { - if (classData.decorators) { - classData.decorators.forEach(validateExpression); - } - if (classData.members) { - Object.getOwnPropertyNames(classData.members) - .forEach(name => classData.members ![name].forEach((m) => validateMember(classData, m))); - } - if (classData.statics) { - Object.getOwnPropertyNames(classData.statics).forEach(name => { - const staticMember = classData.statics ![name]; - if (isFunctionMetadata(staticMember)) { - validateExpression(staticMember.value); - } else { - validateExpression(staticMember); - } - }); - } - } - - function validateFunction(functionDeclaration: FunctionMetadata) { - if (functionDeclaration.value) { - const oldLocals = locals; - if (functionDeclaration.parameters) { - locals = new Set(oldLocals.values()); - if (functionDeclaration.parameters) - functionDeclaration.parameters.forEach(n => locals.add(n)); - } - validateExpression(functionDeclaration.value); - locals = oldLocals; - } - } - - function shouldReportNode(node: ts.Node | undefined) { - if (node) { - const nodeStart = node.getStart(); - return !( - node.pos != nodeStart && - sourceFile.text.substring(node.pos, nodeStart).indexOf('@dynamic') >= 0); - } - return true; - } - - function reportError(error: MetadataError) { - const node = nodeMap.get(error); - if (shouldReportNode(node)) { - const lineInfo = error.line != undefined ? - error.character != undefined ? `:${error.line + 1}:${error.character + 1}` : - `:${error.line + 1}` : - ''; - throw new Error( - `${sourceFile.fileName}${lineInfo}: Metadata collected contains an error that will be reported at runtime: ${expandedMessage(error)}.\n ${JSON.stringify(error)}`); - } - } - - Object.getOwnPropertyNames(metadata).forEach(name => { - const entry = metadata[name]; - try { - if (isClassMetadata(entry)) { - validateClass(entry); - } - } catch (e) { - const node = nodeMap.get(entry); - if (shouldReportNode(node)) { - if (node) { - const {line, character} = sourceFile.getLineAndCharacterOfPosition(node.getStart()); - throw new Error( - `${sourceFile.fileName}:${line + 1}:${character + 1}: Error encountered in metadata generated for exported symbol '${name}': \n ${e.message}`); - } - throw new Error( - `Error encountered in metadata generated for exported symbol ${name}: \n ${e.message}`); - } - } - }); -} - -// Collect parameter names from a function. -function namesOf(parameters: ts.NodeArray): string[] { - const result: string[] = []; - - function addNamesOf(name: ts.Identifier | ts.BindingPattern) { - if (name.kind == ts.SyntaxKind.Identifier) { - const identifier = name; - result.push(identifier.text); - } else { - const bindingPattern = name; - for (const element of bindingPattern.elements) { - const name = (element as any).name; - if (name) { - addNamesOf(name); - } - } - } - } - - for (const parameter of parameters) { - addNamesOf(parameter.name); - } - - return result; -} - -function expandedMessage(error: any): string { - switch (error.message) { - case 'Reference to non-exported class': - if (error.context && error.context.className) { - return `Reference to a non-exported class ${error.context.className}. Consider exporting the class`; - } - break; - case 'Variable not initialized': - return 'Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler'; - case 'Destructuring not supported': - return 'Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring'; - case 'Could not resolve type': - if (error.context && error.context.typeName) { - return `Could not resolve type ${error.context.typeName}`; - } - break; - case 'Function call not supported': - let prefix = - error.context && error.context.name ? `Calling function '${error.context.name}', f` : 'F'; - return prefix + - 'unction calls are not supported. Consider replacing the function or lambda with a reference to an exported function'; - case 'Reference to a local symbol': - if (error.context && error.context.name) { - return `Reference to a local (non-exported) symbol '${error.context.name}'. Consider exporting the symbol`; - } - } - return error.message; -} diff --git a/packages/tsc-wrapped/src/compiler_host.ts b/packages/tsc-wrapped/src/compiler_host.ts deleted file mode 100644 index 47f7358dc7..0000000000 --- a/packages/tsc-wrapped/src/compiler_host.ts +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @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 - */ - -import {writeFileSync} from 'fs'; -import {normalize} from 'path'; -import * as ts from 'typescript'; - -import NgOptions from './options'; -import {MetadataCollector} from './collector'; -import {ModuleMetadata} from './schema'; - -export function formatDiagnostics(d: ts.Diagnostic[]): string { - const host: ts.FormatDiagnosticsHost = { - getCurrentDirectory: () => ts.sys.getCurrentDirectory(), - getNewLine: () => ts.sys.newLine, - getCanonicalFileName: (f: string) => f - }; - return ts.formatDiagnostics(d, host); -} - -/** - * Implementation of CompilerHost that forwards all methods to another instance. - * Useful for partial implementations to override only methods they care about. - */ -export abstract class DelegatingHost implements ts.CompilerHost { - constructor(protected delegate: ts.CompilerHost) {} - getSourceFile = - (fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) => - this.delegate.getSourceFile(fileName, languageVersion, onError); - - getCancellationToken = () => this.delegate.getCancellationToken !(); - getDefaultLibFileName = (options: ts.CompilerOptions) => - this.delegate.getDefaultLibFileName(options); - getDefaultLibLocation = () => this.delegate.getDefaultLibLocation !(); - writeFile: ts.WriteFileCallback = this.delegate.writeFile; - getCurrentDirectory = () => this.delegate.getCurrentDirectory(); - getDirectories = (path: string): string[] => - (this.delegate as any).getDirectories?(this.delegate as any).getDirectories(path): []; - getCanonicalFileName = (fileName: string) => this.delegate.getCanonicalFileName(fileName); - useCaseSensitiveFileNames = () => this.delegate.useCaseSensitiveFileNames(); - getNewLine = () => this.delegate.getNewLine(); - fileExists = (fileName: string) => this.delegate.fileExists(fileName); - readFile = (fileName: string) => this.delegate.readFile(fileName); - trace = (s: string) => this.delegate.trace !(s); - directoryExists = (directoryName: string) => this.delegate.directoryExists !(directoryName); -} - -const IGNORED_FILES = /\.ngfactory\.js$|\.ngstyle\.js$/; -const DTS = /\.d\.ts$/; - -export class MetadataWriterHost extends DelegatingHost { - private metadataCollector = new MetadataCollector({quotedNames: true}); - private metadataCollector1 = new MetadataCollector({version: 1}); - constructor( - delegate: ts.CompilerHost, private ngOptions: NgOptions, private emitAllFiles: boolean) { - super(delegate); - } - - private writeMetadata(emitFilePath: string, sourceFile: ts.SourceFile) { - // TODO: replace with DTS filePath when https://github.com/Microsoft/TypeScript/pull/8412 is - // released - if (/*DTS*/ /\.js$/.test(emitFilePath)) { - const path = emitFilePath.replace(/*DTS*/ /\.js$/, '.metadata.json'); - - // Beginning with 2.1, TypeScript transforms the source tree before emitting it. - // We need the original, unmodified, tree which might be several levels back - // depending on the number of transforms performed. All SourceFile's prior to 2.1 - // will appear to be the original source since they didn't include an original field. - let collectableFile = sourceFile; - while ((collectableFile as any).original) { - collectableFile = (collectableFile as any).original; - } - - const metadata = - this.metadataCollector.getMetadata(collectableFile, !!this.ngOptions.strictMetadataEmit); - const metadata1 = this.metadataCollector1.getMetadata(collectableFile, false); - const metadatas: ModuleMetadata[] = - [metadata, metadata1].filter(e => !!e) as ModuleMetadata[]; - if (metadatas.length) { - const metadataText = JSON.stringify(metadatas); - writeFileSync(path, metadataText, {encoding: 'utf-8'}); - } - } - } - - writeFile: ts.WriteFileCallback = - (fileName: string, data: string, writeByteOrderMark: boolean, - onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => { - const isDts = /\.d\.ts$/.test(fileName); - if (this.emitAllFiles || isDts) { - // Let the original file be written first; this takes care of creating parent directories - this.delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); - } - if (isDts) { - // TODO: remove this early return after https://github.com/Microsoft/TypeScript/pull/8412 - // is released - return; - } - - if (IGNORED_FILES.test(fileName)) { - return; - } - - if (!sourceFiles) { - throw new Error( - 'Metadata emit requires the sourceFiles are passed to WriteFileCallback. ' + - 'Update to TypeScript ^1.9.0-dev'); - } - if (sourceFiles.length > 1) { - throw new Error('Bundled emit with --out is not supported'); - } - if (!this.ngOptions.skipMetadataEmit && !this.ngOptions.flatModuleOutFile) { - this.writeMetadata(fileName, sourceFiles[0]); - } - } -} - -export function createSyntheticIndexHost( - delegate: H, syntheticIndex: {name: string, content: string, metadata: string}): H { - const normalSyntheticIndexName = normalize(syntheticIndex.name); - const indexContent = syntheticIndex.content; - const indexMetadata = syntheticIndex.metadata; - - const newHost = Object.create(delegate); - newHost.fileExists = (fileName: string): boolean => { - return normalize(fileName) == normalSyntheticIndexName || delegate.fileExists(fileName); - }; - - newHost.readFile = (fileName: string) => { - return normalize(fileName) == normalSyntheticIndexName ? indexContent : - delegate.readFile(fileName); - }; - - newHost.getSourceFile = - (fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) => { - if (normalize(fileName) == normalSyntheticIndexName) { - return ts.createSourceFile(fileName, indexContent, languageVersion, true); - } - return delegate.getSourceFile(fileName, languageVersion, onError); - }; - - newHost.writeFile = - (fileName: string, data: string, writeByteOrderMark: boolean, - onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => { - delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); - if (fileName.match(DTS) && sourceFiles && sourceFiles.length == 1 && - normalize(sourceFiles[0].fileName) == normalSyntheticIndexName) { - // If we are writing the synthetic index, write the metadata along side. - const metadataName = fileName.replace(DTS, '.metadata.json'); - writeFileSync(metadataName, indexMetadata, {encoding: 'utf8'}); - } - }; - return newHost; -} \ No newline at end of file diff --git a/packages/tsc-wrapped/src/evaluator.ts b/packages/tsc-wrapped/src/evaluator.ts deleted file mode 100644 index db02169a2b..0000000000 --- a/packages/tsc-wrapped/src/evaluator.ts +++ /dev/null @@ -1,680 +0,0 @@ -/** - * @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 - */ - -import * as ts from 'typescript'; - -import {CollectorOptions} from './collector'; -import {MetadataEntry, MetadataError, MetadataImportedSymbolReferenceExpression, MetadataSymbolicCallExpression, MetadataValue, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSpreadExpression} from './schema'; -import {Symbols} from './symbols'; - - -// In TypeScript 2.1 the spread element kind was renamed. -const spreadElementSyntaxKind: ts.SyntaxKind = - (ts.SyntaxKind as any).SpreadElement || (ts.SyntaxKind as any).SpreadElementExpression; - -function isMethodCallOf(callExpression: ts.CallExpression, memberName: string): boolean { - const expression = callExpression.expression; - if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) { - const propertyAccessExpression = expression; - const name = propertyAccessExpression.name; - if (name.kind == ts.SyntaxKind.Identifier) { - return name.text === memberName; - } - } - return false; -} - -function isCallOf(callExpression: ts.CallExpression, ident: string): boolean { - const expression = callExpression.expression; - if (expression.kind === ts.SyntaxKind.Identifier) { - const identifier = expression; - return identifier.text === ident; - } - return false; -} - -/** - * ts.forEachChild stops iterating children when the callback return a truthy value. - * This method inverts this to implement an `every` style iterator. It will return - * true if every call to `cb` returns `true`. - */ -function everyNodeChild(node: ts.Node, cb: (node: ts.Node) => boolean) { - return !ts.forEachChild(node, node => !cb(node)); -} - -export function isPrimitive(value: any): boolean { - return Object(value) !== value; -} - -function isDefined(obj: any): boolean { - return obj !== undefined; -} - -// import {propertyName as name} from 'place' -// import {name} from 'place' -export interface ImportSpecifierMetadata { - name: string; - propertyName?: string; -} -export interface ImportMetadata { - defaultName?: string; // import d from 'place' - namespace?: string; // import * as d from 'place' - namedImports?: ImportSpecifierMetadata[]; // import {a} from 'place' - from: string; // from 'place' -} - - -function getSourceFileOfNode(node: ts.Node | undefined): ts.SourceFile { - while (node && node.kind != ts.SyntaxKind.SourceFile) { - node = node.parent; - } - return node; -} - -/* @internal */ -export function errorSymbol( - message: string, node?: ts.Node, context?: {[name: string]: string}, - sourceFile?: ts.SourceFile): MetadataError { - let result: MetadataError|undefined = undefined; - if (node) { - sourceFile = sourceFile || getSourceFileOfNode(node); - if (sourceFile) { - const {line, character} = - ts.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)); - result = {__symbolic: 'error', message, line, character}; - } - } - if (!result) { - result = {__symbolic: 'error', message}; - } - if (context) { - result.context = context; - } - return result; -} - -/** - * Produce a symbolic representation of an expression folding values into their final value when - * possible. - */ -export class Evaluator { - constructor( - private symbols: Symbols, private nodeMap: Map, - private options: CollectorOptions = {}, - private recordExport?: (name: string, value: MetadataValue) => void) {} - - nameOf(node: ts.Node|undefined): string|MetadataError { - if (node && node.kind == ts.SyntaxKind.Identifier) { - return (node).text; - } - const result = node && this.evaluateNode(node); - if (isMetadataError(result) || typeof result === 'string') { - return result; - } else { - return errorSymbol( - 'Name expected', node, {received: (node && node.getText()) || ''}); - } - } - - /** - * Returns true if the expression represented by `node` can be folded into a literal expression. - * - * For example, a literal is always foldable. This means that literal expressions such as `1.2` - * `"Some value"` `true` `false` are foldable. - * - * - An object literal is foldable if all the properties in the literal are foldable. - * - An array literal is foldable if all the elements are foldable. - * - A call is foldable if it is a call to a Array.prototype.concat or a call to CONST_EXPR. - * - A property access is foldable if the object is foldable. - * - A array index is foldable if index expression is foldable and the array is foldable. - * - Binary operator expressions are foldable if the left and right expressions are foldable and - * it is one of '+', '-', '*', '/', '%', '||', and '&&'. - * - An identifier is foldable if a value can be found for its symbol in the evaluator symbol - * table. - */ - public isFoldable(node: ts.Node): boolean { - return this.isFoldableWorker(node, new Map()); - } - - private isFoldableWorker(node: ts.Node|undefined, folding: Map): boolean { - if (node) { - switch (node.kind) { - case ts.SyntaxKind.ObjectLiteralExpression: - return everyNodeChild(node, child => { - if (child.kind === ts.SyntaxKind.PropertyAssignment) { - const propertyAssignment = child; - return this.isFoldableWorker(propertyAssignment.initializer, folding); - } - return false; - }); - case ts.SyntaxKind.ArrayLiteralExpression: - return everyNodeChild(node, child => this.isFoldableWorker(child, folding)); - case ts.SyntaxKind.CallExpression: - const callExpression = node; - // We can fold a .concat(). - if (isMethodCallOf(callExpression, 'concat') && - arrayOrEmpty(callExpression.arguments).length === 1) { - const arrayNode = (callExpression.expression).expression; - if (this.isFoldableWorker(arrayNode, folding) && - this.isFoldableWorker(callExpression.arguments[0], folding)) { - // It needs to be an array. - const arrayValue = this.evaluateNode(arrayNode); - if (arrayValue && Array.isArray(arrayValue)) { - return true; - } - } - } - - // We can fold a call to CONST_EXPR - if (isCallOf(callExpression, 'CONST_EXPR') && - arrayOrEmpty(callExpression.arguments).length === 1) - return this.isFoldableWorker(callExpression.arguments[0], folding); - return false; - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.TemplateHead: - case ts.SyntaxKind.TemplateMiddle: - case ts.SyntaxKind.TemplateTail: - return true; - case ts.SyntaxKind.ParenthesizedExpression: - const parenthesizedExpression = node; - return this.isFoldableWorker(parenthesizedExpression.expression, folding); - case ts.SyntaxKind.BinaryExpression: - const binaryExpression = node; - switch (binaryExpression.operatorToken.kind) { - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.AsteriskToken: - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.PercentToken: - case ts.SyntaxKind.AmpersandAmpersandToken: - case ts.SyntaxKind.BarBarToken: - return this.isFoldableWorker(binaryExpression.left, folding) && - this.isFoldableWorker(binaryExpression.right, folding); - default: - return false; - } - case ts.SyntaxKind.PropertyAccessExpression: - const propertyAccessExpression = node; - return this.isFoldableWorker(propertyAccessExpression.expression, folding); - case ts.SyntaxKind.ElementAccessExpression: - const elementAccessExpression = node; - return this.isFoldableWorker(elementAccessExpression.expression, folding) && - this.isFoldableWorker(elementAccessExpression.argumentExpression, folding); - case ts.SyntaxKind.Identifier: - let identifier = node; - let reference = this.symbols.resolve(identifier.text); - if (reference !== undefined && isPrimitive(reference)) { - return true; - } - break; - case ts.SyntaxKind.TemplateExpression: - const templateExpression = node; - return templateExpression.templateSpans.every( - span => this.isFoldableWorker(span.expression, folding)); - } - } - return false; - } - - /** - * Produce a JSON serialiable object representing `node`. The foldable values in the expression - * tree are folded. For example, a node representing `1 + 2` is folded into `3`. - */ - public evaluateNode(node: ts.Node, preferReference?: boolean): MetadataValue { - const t = this; - let error: MetadataError|undefined; - - function recordEntry(entry: MetadataValue, node: ts.Node): MetadataValue { - if (t.options.substituteExpression) { - const newEntry = t.options.substituteExpression(entry, node); - if (t.recordExport && newEntry != entry && isMetadataGlobalReferenceExpression(newEntry)) { - t.recordExport(newEntry.name, entry); - } - entry = newEntry; - } - t.nodeMap.set(entry, node); - return entry; - } - - function isFoldableError(value: any): value is MetadataError { - return !t.options.verboseInvalidExpression && isMetadataError(value); - } - - const resolveName = (name: string, preferReference?: boolean): MetadataValue => { - const reference = this.symbols.resolve(name, preferReference); - if (reference === undefined) { - // Encode as a global reference. StaticReflector will check the reference. - return recordEntry({__symbolic: 'reference', name}, node); - } - return reference; - }; - - switch (node.kind) { - case ts.SyntaxKind.ObjectLiteralExpression: - let obj: {[name: string]: any} = {}; - let quoted: string[] = []; - ts.forEachChild(node, child => { - switch (child.kind) { - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.PropertyAssignment: - const assignment = child; - if (assignment.name.kind == ts.SyntaxKind.StringLiteral) { - const name = (assignment.name as ts.StringLiteral).text; - quoted.push(name); - } - const propertyName = this.nameOf(assignment.name); - if (isFoldableError(propertyName)) { - error = propertyName; - return true; - } - const propertyValue = isPropertyAssignment(assignment) ? - this.evaluateNode(assignment.initializer, /* preferReference */ true) : - resolveName(propertyName, /* preferReference */ true); - if (isFoldableError(propertyValue)) { - error = propertyValue; - return true; // Stop the forEachChild. - } else { - obj[propertyName] = isPropertyAssignment(assignment) ? - recordEntry(propertyValue, assignment.initializer) : - propertyValue; - } - } - }); - if (error) return error; - if (this.options.quotedNames && quoted.length) { - obj['$quoted$'] = quoted; - } - return recordEntry(obj, node); - case ts.SyntaxKind.ArrayLiteralExpression: - let arr: MetadataValue[] = []; - ts.forEachChild(node, child => { - const value = this.evaluateNode(child, /* preferReference */ true); - - // Check for error - if (isFoldableError(value)) { - error = value; - return true; // Stop the forEachChild. - } - - // Handle spread expressions - if (isMetadataSymbolicSpreadExpression(value)) { - if (Array.isArray(value.expression)) { - for (const spreadValue of value.expression) { - arr.push(spreadValue); - } - return; - } - } - - arr.push(value); - }); - if (error) return error; - return recordEntry(arr, node); - case spreadElementSyntaxKind: - let spreadExpression = this.evaluateNode((node as any).expression); - return recordEntry({__symbolic: 'spread', expression: spreadExpression}, node); - case ts.SyntaxKind.CallExpression: - const callExpression = node; - if (isCallOf(callExpression, 'forwardRef') && - arrayOrEmpty(callExpression.arguments).length === 1) { - const firstArgument = callExpression.arguments[0]; - if (firstArgument.kind == ts.SyntaxKind.ArrowFunction) { - const arrowFunction = firstArgument; - return recordEntry(this.evaluateNode(arrowFunction.body), node); - } - } - const args = arrayOrEmpty(callExpression.arguments).map(arg => this.evaluateNode(arg)); - if (!this.options.verboseInvalidExpression && args.some(isMetadataError)) { - return args.find(isMetadataError); - } - if (this.isFoldable(callExpression)) { - if (isMethodCallOf(callExpression, 'concat')) { - const arrayValue = this.evaluateNode( - (callExpression.expression).expression); - if (isFoldableError(arrayValue)) return arrayValue; - return arrayValue.concat(args[0]); - } - } - // Always fold a CONST_EXPR even if the argument is not foldable. - if (isCallOf(callExpression, 'CONST_EXPR') && - arrayOrEmpty(callExpression.arguments).length === 1) { - return recordEntry(args[0], node); - } - const expression = this.evaluateNode(callExpression.expression); - if (isFoldableError(expression)) { - return recordEntry(expression, node); - } - let result: MetadataSymbolicCallExpression = {__symbolic: 'call', expression: expression}; - if (args && args.length) { - result.arguments = args; - } - return recordEntry(result, node); - case ts.SyntaxKind.NewExpression: - const newExpression = node; - const newArgs = arrayOrEmpty(newExpression.arguments).map(arg => this.evaluateNode(arg)); - if (!this.options.verboseInvalidExpression && newArgs.some(isMetadataError)) { - return recordEntry(newArgs.find(isMetadataError), node); - } - const newTarget = this.evaluateNode(newExpression.expression); - if (isMetadataError(newTarget)) { - return recordEntry(newTarget, node); - } - const call: MetadataSymbolicCallExpression = {__symbolic: 'new', expression: newTarget}; - if (newArgs.length) { - call.arguments = newArgs; - } - return recordEntry(call, node); - case ts.SyntaxKind.PropertyAccessExpression: { - const propertyAccessExpression = node; - const expression = this.evaluateNode(propertyAccessExpression.expression); - if (isFoldableError(expression)) { - return recordEntry(expression, node); - } - const member = this.nameOf(propertyAccessExpression.name); - if (isFoldableError(member)) { - return recordEntry(member, node); - } - if (expression && this.isFoldable(propertyAccessExpression.expression)) - return (expression)[member]; - if (isMetadataModuleReferenceExpression(expression)) { - // A select into a module reference and be converted into a reference to the symbol - // in the module - return recordEntry( - {__symbolic: 'reference', module: expression.module, name: member}, node); - } - return recordEntry({__symbolic: 'select', expression, member}, node); - } - case ts.SyntaxKind.ElementAccessExpression: { - const elementAccessExpression = node; - const expression = this.evaluateNode(elementAccessExpression.expression); - if (isFoldableError(expression)) { - return recordEntry(expression, node); - } - if (!elementAccessExpression.argumentExpression) { - return recordEntry(errorSymbol('Expression form not supported', node), node); - } - const index = this.evaluateNode(elementAccessExpression.argumentExpression); - if (isFoldableError(expression)) { - return recordEntry(expression, node); - } - if (this.isFoldable(elementAccessExpression.expression) && - this.isFoldable(elementAccessExpression.argumentExpression)) - return (expression)[index]; - return recordEntry({__symbolic: 'index', expression, index}, node); - } - case ts.SyntaxKind.Identifier: - const identifier = node; - const name = identifier.text; - return resolveName(name, preferReference); - case ts.SyntaxKind.TypeReference: - const typeReferenceNode = node; - const typeNameNode = typeReferenceNode.typeName; - const getReference: (typeNameNode: ts.Identifier | ts.QualifiedName) => MetadataValue = - node => { - if (typeNameNode.kind === ts.SyntaxKind.QualifiedName) { - const qualifiedName = node; - const left = this.evaluateNode(qualifiedName.left); - if (isMetadataModuleReferenceExpression(left)) { - return recordEntry( - { - __symbolic: 'reference', - module: left.module, - name: qualifiedName.right.text - }, - node); - } - // Record a type reference to a declared type as a select. - return {__symbolic: 'select', expression: left, member: qualifiedName.right.text}; - } else { - const identifier = typeNameNode; - const symbol = this.symbols.resolve(identifier.text); - if (isFoldableError(symbol) || isMetadataSymbolicReferenceExpression(symbol)) { - return recordEntry(symbol, node); - } - return recordEntry( - errorSymbol('Could not resolve type', node, {typeName: identifier.text}), node); - } - }; - const typeReference = getReference(typeNameNode); - if (isFoldableError(typeReference)) { - return recordEntry(typeReference, node); - } - if (!isMetadataModuleReferenceExpression(typeReference) && - typeReferenceNode.typeArguments && typeReferenceNode.typeArguments.length) { - const args = typeReferenceNode.typeArguments.map(element => this.evaluateNode(element)); - // TODO: Remove typecast when upgraded to 2.0 as it will be corretly inferred. - // Some versions of 1.9 do not infer this correctly. - (typeReference).arguments = args; - } - return recordEntry(typeReference, node); - case ts.SyntaxKind.UnionType: - const unionType = node; - - // Remove null and undefined from the list of unions. - const references = unionType.types - .filter( - n => n.kind != ts.SyntaxKind.NullKeyword && - n.kind != ts.SyntaxKind.UndefinedKeyword) - .map(n => this.evaluateNode(n)); - - // The remmaining reference must be the same. If two have type arguments consider them - // different even if the type arguments are the same. - let candidate: any = null; - for (let i = 0; i < references.length; i++) { - const reference = references[i]; - if (isMetadataSymbolicReferenceExpression(reference)) { - if (candidate) { - if ((reference as any).name == candidate.name && - (reference as any).module == candidate.module && !(reference as any).arguments) { - candidate = reference; - } - } else { - candidate = reference; - } - } else { - return reference; - } - } - if (candidate) return candidate; - break; - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.TemplateHead: - case ts.SyntaxKind.TemplateTail: - case ts.SyntaxKind.TemplateMiddle: - return (node).text; - case ts.SyntaxKind.NumericLiteral: - return parseFloat((node).text); - case ts.SyntaxKind.AnyKeyword: - return recordEntry({__symbolic: 'reference', name: 'any'}, node); - case ts.SyntaxKind.StringKeyword: - return recordEntry({__symbolic: 'reference', name: 'string'}, node); - case ts.SyntaxKind.NumberKeyword: - return recordEntry({__symbolic: 'reference', name: 'number'}, node); - case ts.SyntaxKind.BooleanKeyword: - return recordEntry({__symbolic: 'reference', name: 'boolean'}, node); - case ts.SyntaxKind.ArrayType: - const arrayTypeNode = node; - return recordEntry( - { - __symbolic: 'reference', - name: 'Array', - arguments: [this.evaluateNode(arrayTypeNode.elementType)] - }, - node); - case ts.SyntaxKind.NullKeyword: - return null; - case ts.SyntaxKind.TrueKeyword: - return true; - case ts.SyntaxKind.FalseKeyword: - return false; - case ts.SyntaxKind.ParenthesizedExpression: - const parenthesizedExpression = node; - return this.evaluateNode(parenthesizedExpression.expression); - case ts.SyntaxKind.TypeAssertionExpression: - const typeAssertion = node; - return this.evaluateNode(typeAssertion.expression); - case ts.SyntaxKind.PrefixUnaryExpression: - const prefixUnaryExpression = node; - const operand = this.evaluateNode(prefixUnaryExpression.operand); - if (isDefined(operand) && isPrimitive(operand)) { - switch (prefixUnaryExpression.operator) { - case ts.SyntaxKind.PlusToken: - return +(operand as any); - case ts.SyntaxKind.MinusToken: - return -(operand as any); - case ts.SyntaxKind.TildeToken: - return ~(operand as any); - case ts.SyntaxKind.ExclamationToken: - return !operand; - } - } - let operatorText: string; - switch (prefixUnaryExpression.operator) { - case ts.SyntaxKind.PlusToken: - operatorText = '+'; - break; - case ts.SyntaxKind.MinusToken: - operatorText = '-'; - break; - case ts.SyntaxKind.TildeToken: - operatorText = '~'; - break; - case ts.SyntaxKind.ExclamationToken: - operatorText = '!'; - break; - default: - return undefined; - } - return recordEntry({__symbolic: 'pre', operator: operatorText, operand: operand}, node); - case ts.SyntaxKind.BinaryExpression: - const binaryExpression = node; - const left = this.evaluateNode(binaryExpression.left); - const right = this.evaluateNode(binaryExpression.right); - if (isDefined(left) && isDefined(right)) { - if (isPrimitive(left) && isPrimitive(right)) - switch (binaryExpression.operatorToken.kind) { - case ts.SyntaxKind.BarBarToken: - return left || right; - case ts.SyntaxKind.AmpersandAmpersandToken: - return left && right; - case ts.SyntaxKind.AmpersandToken: - return left & right; - case ts.SyntaxKind.BarToken: - return left | right; - case ts.SyntaxKind.CaretToken: - return left ^ right; - case ts.SyntaxKind.EqualsEqualsToken: - return left == right; - case ts.SyntaxKind.ExclamationEqualsToken: - return left != right; - case ts.SyntaxKind.EqualsEqualsEqualsToken: - return left === right; - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - return left !== right; - case ts.SyntaxKind.LessThanToken: - return left < right; - case ts.SyntaxKind.GreaterThanToken: - return left > right; - case ts.SyntaxKind.LessThanEqualsToken: - return left <= right; - case ts.SyntaxKind.GreaterThanEqualsToken: - return left >= right; - case ts.SyntaxKind.LessThanLessThanToken: - return (left) << (right); - case ts.SyntaxKind.GreaterThanGreaterThanToken: - return left >> right; - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - return left >>> right; - case ts.SyntaxKind.PlusToken: - return left + right; - case ts.SyntaxKind.MinusToken: - return left - right; - case ts.SyntaxKind.AsteriskToken: - return left * right; - case ts.SyntaxKind.SlashToken: - return left / right; - case ts.SyntaxKind.PercentToken: - return left % right; - } - return recordEntry( - { - __symbolic: 'binop', - operator: binaryExpression.operatorToken.getText(), - left: left, - right: right - }, - node); - } - break; - case ts.SyntaxKind.ConditionalExpression: - const conditionalExpression = node; - const condition = this.evaluateNode(conditionalExpression.condition); - const thenExpression = this.evaluateNode(conditionalExpression.whenTrue); - const elseExpression = this.evaluateNode(conditionalExpression.whenFalse); - if (isPrimitive(condition)) { - return condition ? thenExpression : elseExpression; - } - return recordEntry({__symbolic: 'if', condition, thenExpression, elseExpression}, node); - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - return recordEntry(errorSymbol('Function call not supported', node), node); - case ts.SyntaxKind.TaggedTemplateExpression: - return recordEntry( - errorSymbol('Tagged template expressions are not supported in metadata', node), node); - case ts.SyntaxKind.TemplateExpression: - const templateExpression = node; - if (this.isFoldable(node)) { - return templateExpression.templateSpans.reduce( - (previous, current) => previous + this.evaluateNode(current.expression) + - this.evaluateNode(current.literal), - this.evaluateNode(templateExpression.head)); - } else { - return templateExpression.templateSpans.reduce((previous, current) => { - const expr = this.evaluateNode(current.expression); - const literal = this.evaluateNode(current.literal); - if (isFoldableError(expr)) return expr; - if (isFoldableError(literal)) return literal; - if (typeof previous === 'string' && typeof expr === 'string' && - typeof literal === 'string') { - return previous + expr + literal; - } - let result = expr; - if (previous !== '') { - result = {__symbolic: 'binop', operator: '+', left: previous, right: expr}; - } - if (literal != '') { - result = {__symbolic: 'binop', operator: '+', left: result, right: literal}; - } - return result; - }, this.evaluateNode(templateExpression.head)); - } - case ts.SyntaxKind.AsExpression: - const asExpression = node; - return this.evaluateNode(asExpression.expression); - case ts.SyntaxKind.ClassExpression: - return {__symbolic: 'class'}; - } - return recordEntry(errorSymbol('Expression form not supported', node), node); - } -} - -function isPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment { - return node.kind == ts.SyntaxKind.PropertyAssignment; -} - -const empty = ts.createNodeArray(); - -function arrayOrEmpty(v: ts.NodeArray| undefined): ts.NodeArray { - return v || empty; -} \ No newline at end of file diff --git a/packages/tsc-wrapped/src/index_writer.ts b/packages/tsc-wrapped/src/index_writer.ts deleted file mode 100644 index 2c209f1c5b..0000000000 --- a/packages/tsc-wrapped/src/index_writer.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @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 - */ - -import {BundlePrivateEntry} from './bundler'; - -const INDEX_HEADER = `/** - * Generated bundle index. Do not edit. - */ -`; - -type MapEntry = [string, BundlePrivateEntry[]]; - -export function privateEntriesToIndex(index: string, privates: BundlePrivateEntry[]): string { - const results: string[] = [INDEX_HEADER]; - - // Export all of the index symbols. - results.push(`export * from '${index}';`, ''); - - // Simplify the exports - const exports = new Map(); - - for (const entry of privates) { - let entries = exports.get(entry.module); - if (!entries) { - entries = []; - exports.set(entry.module, entries); - } - entries.push(entry); - } - - - const compareEntries = compare((e: BundlePrivateEntry) => e.name); - const compareModules = compare((e: MapEntry) => e[0]); - const orderedExports = - Array.from(exports) - .map(([module, entries]) => [module, entries.sort(compareEntries)]) - .sort(compareModules); - - for (const [module, entries] of orderedExports) { - let symbols = entries.map(e => `${e.name} as ${e.privateName}`); - results.push(`export {${symbols}} from '${module}';`); - } - - return results.join('\n'); -} - -function compare(select: (e: E) => T): (a: E, b: E) => number { - return (a, b) => { - const ak = select(a); - const bk = select(b); - return ak > bk ? 1 : ak < bk ? -1 : 0; - }; -} \ No newline at end of file diff --git a/packages/tsc-wrapped/src/main.ts b/packages/tsc-wrapped/src/main.ts deleted file mode 100644 index 71c5616b34..0000000000 --- a/packages/tsc-wrapped/src/main.ts +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @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 - */ - -import * as fs from 'fs'; -import * as path from 'path'; -import * as tsickle from 'tsickle'; -import * as ts from 'typescript'; - -import {CliOptions} from './cli_options'; -import {MetadataWriterHost} from './compiler_host'; - -import {CodegenExtension, createBundleIndexHost} from './main_no_tsickle'; -import {check, tsc} from './tsc'; -import {VinylFile, isVinylFile} from './vinyl_file'; - -const TS_EXT = /\.ts$/; - -export function main( - project: string | VinylFile, cliOptions: CliOptions, codegen?: CodegenExtension, - options?: ts.CompilerOptions): Promise { - try { - let projectDir = project; - // project is vinyl like file object - if (isVinylFile(project)) { - projectDir = path.dirname(project.path); - } - // project is path to project file - else if (fs.lstatSync(project).isFile()) { - projectDir = path.dirname(project); - } - - // file names in tsconfig are resolved relative to this absolute path - const basePath = path.resolve(process.cwd(), cliOptions.basePath || projectDir); - - // read the configuration options from wherever you store them - let {parsed, ngOptions} = tsc.readConfiguration(project, basePath, options); - ngOptions.basePath = basePath; - let rootFileNames: string[] = parsed.fileNames.slice(0); - const createProgram = (host: ts.CompilerHost, oldProgram?: ts.Program) => { - return ts.createProgram(rootFileNames.slice(0), parsed.options, host, oldProgram); - }; - const addGeneratedFileName = (genFileName: string) => { - if (genFileName.startsWith(basePath) && TS_EXT.exec(genFileName)) { - rootFileNames.push(genFileName); - } - }; - - const diagnostics = (parsed.options as any).diagnostics; - if (diagnostics) (ts as any).performance.enable(); - - let host = ts.createCompilerHost(parsed.options, true); - // Make sure we do not `host.realpath()` from TS as we do not want to resolve symlinks. - // https://github.com/Microsoft/TypeScript/issues/9552 - host.realpath = (fileName: string) => fileName; - - // If the compilation is a flat module index then produce the flat module index - // metadata and the synthetic flat module index. - if (ngOptions.flatModuleOutFile && !ngOptions.skipMetadataEmit) { - const {host: bundleHost, indexName, errors} = - createBundleIndexHost(ngOptions, rootFileNames, host); - if (errors) check(errors); - if (indexName) addGeneratedFileName(indexName); - host = bundleHost; - } - - const tsickleHost: tsickle.TsickleHost = { - shouldSkipTsickleProcessing: (fileName) => /\.d\.ts$/.test(fileName), - pathToModuleName: (context, importPath) => '', - shouldIgnoreWarningsForPath: (filePath) => false, - fileNameToModuleId: (fileName) => fileName, - googmodule: false, - untyped: true, - convertIndexImportShorthand: false, - transformDecorators: ngOptions.annotationsAs !== 'decorators', - transformTypesToClosure: ngOptions.annotateForClosureCompiler, - }; - - const program = createProgram(host); - - const errors = program.getOptionsDiagnostics(); - check(errors); - - if (ngOptions.skipTemplateCodegen || !codegen) { - codegen = () => Promise.resolve([]); - } - - if (diagnostics) console.time('NG codegen'); - return codegen(ngOptions, cliOptions, program, host).then((genFiles) => { - if (diagnostics) console.timeEnd('NG codegen'); - - // Add the generated files to the configuration so they will become part of the program. - if (ngOptions.alwaysCompileGeneratedCode) { - genFiles.forEach(genFileName => addGeneratedFileName(genFileName)); - } - if (!ngOptions.skipMetadataEmit) { - host = new MetadataWriterHost(host, ngOptions, true); - } - - // Create a new program since codegen files were created after making the old program - let programWithCodegen = createProgram(host, program); - tsc.typeCheck(host, programWithCodegen); - - if (diagnostics) console.time('Emit'); - const {diagnostics: emitDiags} = - tsickle.emitWithTsickle(programWithCodegen, tsickleHost, host, ngOptions); - if (diagnostics) console.timeEnd('Emit'); - check(emitDiags); - - if (diagnostics) { - (ts as any).performance.forEachMeasure( - (name: string, duration: number) => { console.error(`TS ${name}: ${duration}ms`); }); - } - }); - } catch (e) { - return Promise.reject(e); - } -} - -// CLI entry point -if (require.main === module) { - const args = process.argv.slice(2); - let {options, errors} = (ts as any).parseCommandLine(args); - check(errors); - const project = options.project || '.'; - // TODO(alexeagle): command line should be TSC-compatible, remove "CliOptions" here - const cliOptions = new CliOptions(require('minimist')(args)); - main(project, cliOptions, undefined, options) - .then((exitCode: any) => process.exit(exitCode)) - .catch((e: any) => { - console.error(e.stack); - console.error('Compilation failed'); - process.exit(1); - }); -} diff --git a/packages/tsc-wrapped/src/main_no_tsickle.ts b/packages/tsc-wrapped/src/main_no_tsickle.ts deleted file mode 100644 index 8097b085bc..0000000000 --- a/packages/tsc-wrapped/src/main_no_tsickle.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @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 - */ - -import * as path from 'path'; -import * as ts from 'typescript'; - -import {CompilerHostAdapter, MetadataBundler} from './bundler'; -import {CliOptions} from './cli_options'; -import {createSyntheticIndexHost} from './compiler_host'; -import {privateEntriesToIndex} from './index_writer'; -import NgOptions from './options'; - -export {UserError} from './tsc'; - -export interface CodegenExtension { - /** - * Returns the generated file names. - */ - (ngOptions: NgOptions, cliOptions: CliOptions, program: ts.Program, - host: ts.CompilerHost): Promise; -} - -const DTS = /\.d\.ts$/; -const JS_EXT = /(\.js|)$/; - -export function createBundleIndexHost( - ngOptions: NgOptions, rootFiles: string[], - host: H): {host: H, indexName?: string, errors?: ts.Diagnostic[]} { - const files = rootFiles.filter(f => !DTS.test(f)); - if (files.length != 1) { - return { - host, - errors: [{ - file: null as any as ts.SourceFile, - start: null as any as number, - length: null as any as number, - messageText: - 'Angular compiler option "flatModuleIndex" requires one and only one .ts file in the "files" field.', - category: ts.DiagnosticCategory.Error, - code: 0 - }] - }; - } - const file = files[0]; - const indexModule = file.replace(/\.ts$/, ''); - const bundler = - new MetadataBundler(indexModule, ngOptions.flatModuleId, new CompilerHostAdapter(host)); - const metadataBundle = bundler.getMetadataBundle(); - const metadata = JSON.stringify(metadataBundle.metadata); - const name = - path.join(path.dirname(indexModule), ngOptions.flatModuleOutFile !.replace(JS_EXT, '.ts')); - const libraryIndex = `./${path.basename(indexModule)}`; - const content = privateEntriesToIndex(libraryIndex, metadataBundle.privates); - host = createSyntheticIndexHost(host, {name, content, metadata}); - return {host, indexName: name}; -} \ No newline at end of file diff --git a/packages/tsc-wrapped/src/options.ts b/packages/tsc-wrapped/src/options.ts deleted file mode 100644 index 8efa7243c0..0000000000 --- a/packages/tsc-wrapped/src/options.ts +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @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 - */ - -import * as ts from 'typescript'; - -interface Options extends ts.CompilerOptions { - // Absolute path to a directory where generated file structure is written. - // If unspecified, generated files will be written alongside sources. - genDir?: string; - - // Path to the directory containing the tsconfig.json file. - basePath?: string; - - // Don't produce .metadata.json files (they don't work for bundled emit with --out) - skipMetadataEmit?: boolean; - - // Produce an error if the metadata written for a class would produce an error if used. - strictMetadataEmit?: boolean; - - // Don't produce .ngfactory.ts or .ngstyle.ts files - skipTemplateCodegen?: boolean; - - // Whether to generate a flat module index of the given name and the corresponding - // flat module metadata. This option is intended to be used when creating flat - // modules similar to how `@angular/core` and `@angular/common` are packaged. - // When this option is used the `package.json` for the library should referred to the - // generated flat module index instead of the library index file. When using this - // option only one .metadata.json file is produced that contains all the metadata - // necessary for symbols exported from the library index. - // In the generated .ngfactory.ts files flat module index is used to import symbols - // includes both the public API from the library index as well as shrowded internal - // symbols. - // By default the .ts file supplied in the `files` files field is assumed to be - // library index. If more than one is specified, uses `libraryIndex` to select the - // file to use. If more than on .ts file is supplied and no `libraryIndex` is supplied - // an error is produced. - // A flat module index .d.ts and .js will be created with the given `flatModuleOutFile` - // name in the same location as the library index .d.ts file is emitted. - // For example, if a library uses `public_api.ts` file as the library index of the - // module the `tsconfig.json` `files` field would be `["public_api.ts"]`. The - // `flatModuleOutFile` options could then be set to, for example `"index.js"`, which - // produces `index.d.ts` and `index.metadata.json` files. The library's - // `package.json`'s `module` field would be `"index.js"` and the `typings` field would - // be `"index.d.ts"`. - flatModuleOutFile?: string; - - // Preferred module id to use for importing flat module. References generated by `ngc` - // will use this module name when importing symbols from the flat module. This is only - // meaningful when `flatModuleOutFile` is also supplied. It is otherwise ignored. - flatModuleId?: string; - - // Whether to generate code for library code. - // If true, produce .ngfactory.ts and .ngstyle.ts files for .d.ts inputs. - // Default is true. - generateCodeForLibraries?: boolean; - - // Insert JSDoc type annotations needed by Closure Compiler - annotateForClosureCompiler?: boolean; - - // Modify how angular annotations are emitted to improve tree-shaking. - // Default is static fields. - // decorators: Leave the Decorators in-place. This makes compilation faster. - // TypeScript will emit calls to the __decorate helper. - // `--emitDecoratorMetadata` can be used for runtime reflection. - // However, the resulting code will not properly tree-shake. - // static fields: Replace decorators with a static field in the class. - // Allows advanced tree-shakers like Closure Compiler to remove - // unused classes. - annotationsAs?: 'decorators'|'static fields'; - - // Print extra information while running the compiler - trace?: boolean; - - // Whether to enable support for