Compare commits

...

10 Commits

Author SHA1 Message Date
47bc6f105d docs: add changelog for 5.0.0-rc.6 2017-10-25 14:34:42 -07:00
40fa2593a9 release: cut the 5.0.0-rc.6 release 2017-10-25 14:32:11 -07:00
680bcf7b8a build: update to rxjs@5.5.2 (#19931)
PR Close #19931
2017-10-25 15:32:01 -04:00
ef08330341 fix(compiler): automatically set emitDecoratorMetadata when "annotationsAs": "static fields” (#19927)
This is a workaround for https://github.com/angular/tsickle/issues/635.

Fixes #19916
PR Close #19927
2017-10-25 14:26:28 -04:00
6cc042e2ba fix(compiler-cli): produce correct paths for windows output (#19915)
The path mapping was broken for Windows by fc0b1d5b61.
Fixed the path mapping and put code in place to make such a problem
to sneek by again.

PR Close #19915
2017-10-24 19:21:18 -04:00
9b26455740 fix(compiler-cli): only use error collector when needed. (#19912)
The error collector changes behavior of the metadata resolver
in ways that haven't been fully hardened. This changes limits
its use to the lazy route detection and the language service.

Issue: #19906

PR Close #19912
2017-10-24 19:21:13 -04:00
18bce5987c fix(compiler): don’t type check templates with skipTemplateCodegen (#19909)
This change is needed to prevent users’ builds from breaking.

If a user sets `fullTemlateTypeCheck` to true, we will
continue to check the templates even when `skipTemplateCodegen` is true
as well.

Related to #19906

PR Close #19909
2017-10-24 19:21:03 -04:00
f1108fea76 docs: add changelog for 5.0.0-rc.5 2017-10-23 23:28:28 -07:00
64b3e3e41a release: cut the 5.0.0-rc.5 release 2017-10-23 23:27:15 -07:00
a82f863e24 fix(compiler-cli): report all diagnostic error messages (#19886)
This fixes a problem introduced in 8d45fefc31
which modified how diagnostic error messages are reported for structural
metadata errors causing some of the diagnostics to be lost.

PR Close #19886
2017-10-24 00:57:41 -04:00
13 changed files with 213 additions and 61 deletions

View File

@ -1,3 +1,26 @@
<a name="5.0.0-rc.6"></a>
# [5.0.0-rc.6](https://github.com/angular/angular/compare/5.0.0-rc.5...5.0.0-rc.6) (2017-10-25)
### Bug Fixes
* **compiler:** automatically set `emitDecoratorMetadata` when `"annotationsAs": "static fields”` ([#19927](https://github.com/angular/angular/issues/19927)) ([ef08330](https://github.com/angular/angular/commit/ef08330)), closes [#19916](https://github.com/angular/angular/issues/19916)
* **compiler:** dont type check templates with `skipTemplateCodegen` ([#19909](https://github.com/angular/angular/issues/19909)) ([18bce59](https://github.com/angular/angular/commit/18bce59))
* **compiler-cli:** only use error collector when needed. ([#19912](https://github.com/angular/angular/issues/19912)) ([9b26455](https://github.com/angular/angular/commit/9b26455))
* **compiler-cli:** produce correct paths for windows output ([#19915](https://github.com/angular/angular/issues/19915)) ([6cc042e](https://github.com/angular/angular/commit/6cc042e))
<a name="5.0.0-rc.5"></a>
# [5.0.0-rc.5](https://github.com/angular/angular/compare/5.0.0-rc.4...5.0.0-rc.5) (2017-10-24)
### Bug Fixes
* **compiler-cli:** report all diagnostic error messages ([#19886](https://github.com/angular/angular/issues/19886)) ([a82f863](https://github.com/angular/angular/commit/a82f863))
<a name="5.0.0-rc.4"></a>
# [5.0.0-rc.4](https://github.com/angular/angular/compare/5.0.0-rc.3...5.0.0-rc.4) (2017-10-24)

View File

@ -1,6 +1,6 @@
{
"name": "angular-srcs",
"version": "5.0.0-rc.4",
"version": "5.0.0-rc.6",
"private": true,
"branchPattern": "2.0.*",
"description": "Angular - a web framework for modern web apps",
@ -24,7 +24,7 @@
"dependencies": {
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "^5.5.0",
"rxjs": "^5.5.2",
"tslib": "^1.7.1",
"zone.js": "^0.8.12"
},

View File

@ -45,6 +45,12 @@ function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|un
if (!transformDecorators && !transformTypesToClosure) {
return undefined;
}
if (transformDecorators) {
// This is needed as a workaround for https://github.com/angular/tsickle/issues/635
// Otherwise tsickle might emit references to non imported values
// as TypeScript elided the import.
options.emitDecoratorMetadata = true;
}
const tsickleHost: tsickle.TsickleHost = {
shouldSkipTsickleProcessing: (fileName) =>
/\.d\.ts$/.test(fileName) || GENERATED_FILES.test(fileName),

View File

@ -89,7 +89,7 @@ export class NgTools_InternalApi_NG_2 {
// as we only needed this to support Angular CLI 1.5.0 rc.*
const ngProgram = createProgram({
rootNames: options.program.getRootFileNames(),
options: options.angularCompilerOptions,
options: {...options.angularCompilerOptions, collectAllErrors: true},
host: options.host
});
const lazyRoutes = ngProgram.listLazyRoutes(options.entryModule);

View File

@ -150,6 +150,9 @@ export interface CompilerOptions extends ts.CompilerOptions {
* in JIT mode. This is off by default.
*/
enableSummariesForJit?: boolean;
/** @internal */
collectAllErrors?: boolean;
}
export interface CompilerHost extends ts.CompilerHost {

View File

@ -426,6 +426,12 @@ export class TsCompilerAotCompilerTypeCheckHostAdapter implements ts.CompilerHos
}
isSourceFile(filePath: string): boolean {
// Don't generate any files nor typecheck them
// if skipTemplateCodegen is set and fullTemplateTypeCheck is not yet set,
// for backwards compatibility.
if (this.options.skipTemplateCodegen && !this.options.fullTemplateTypeCheck) {
return false;
}
// If we have a summary from a previous compilation,
// treat the file never as a source file.
if (this.librarySummaries.has(filePath)) {

View File

@ -181,11 +181,13 @@ function createVariableStatementForDeclarations(declarations: Declaration[]): ts
/* modifiers */ undefined, ts.createVariableDeclarationList(varDecls, ts.NodeFlags.Const));
}
export function getExpressionLoweringTransformFactory(requestsMap: RequestsMap):
(context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile {
export function getExpressionLoweringTransformFactory(
requestsMap: RequestsMap, program: ts.Program): (context: ts.TransformationContext) =>
(sourceFile: ts.SourceFile) => ts.SourceFile {
// Return the factory
return (context: ts.TransformationContext) => (sourceFile: ts.SourceFile): ts.SourceFile => {
const requests = requestsMap.getRequests(sourceFile);
// We need to use the original SourceFile for reading metadata, and not the transformed one.
const requests = requestsMap.getRequests(program.getSourceFile(sourceFile.fileName));
if (requests && requests.size) {
return transformSourceFile(sourceFile, requests, context);
}

View File

@ -386,7 +386,7 @@ class AngularCompilerProgram implements Program {
customTransformers?: CustomTransformers): ts.CustomTransformers {
const beforeTs: ts.TransformerFactory<ts.SourceFile>[] = [];
if (!this.options.disableExpressionLowering) {
beforeTs.push(getExpressionLoweringTransformFactory(this.metadataCache));
beforeTs.push(getExpressionLoweringTransformFactory(this.metadataCache, this.tsProgram));
}
beforeTs.push(getAngularEmitterTransformFactory(genFiles));
if (customTransformers && customTransformers.beforeTs) {
@ -422,14 +422,15 @@ class AngularCompilerProgram implements Program {
this.oldProgramLibrarySummaries);
const aotOptions = getAotCompilerOptions(this.options);
this._structuralDiagnostics = [];
const errorCollector = (err: any) => {
const errorCollector =
(this.options.collectAllErrors || this.options.fullTemplateTypeCheck) ? (err: any) => {
this._structuralDiagnostics !.push({
messageText: err.toString(),
category: ts.DiagnosticCategory.Error,
source: SOURCE,
code: DEFAULT_ERROR_CODE
});
};
} : undefined;
this._compiler = createAotCompiler(this._hostAdapter, aotOptions, errorCollector).compiler;
}
@ -510,21 +511,25 @@ class AngularCompilerProgram implements Program {
if (isSyntaxError(e)) {
const parserErrors = getParseErrors(e);
if (parserErrors && parserErrors.length) {
this._structuralDiagnostics =
parserErrors.map<Diagnostic>(e => ({
this._structuralDiagnostics = [
...(this._structuralDiagnostics || []),
...parserErrors.map<Diagnostic>(e => ({
messageText: e.contextualMessage(),
category: ts.DiagnosticCategory.Error,
span: e.span,
source: SOURCE,
code: DEFAULT_ERROR_CODE
}));
}))
];
} else {
this._structuralDiagnostics = [{
this._structuralDiagnostics = [
...(this._structuralDiagnostics || []), {
messageText: e.message,
category: ts.DiagnosticCategory.Error,
source: SOURCE,
code: DEFAULT_ERROR_CODE
}];
}
];
}
return null;
}
@ -702,6 +707,10 @@ function getNgOptionDiagnostics(options: CompilerOptions): Diagnostic[] {
return [];
}
function normalizeSeparators(path: string): string {
return path.replace(/\\/g, '/');
}
/**
* Returns a function that can adjust a path from source path to out path,
* based on an existing mapping from source to out path.
@ -723,18 +732,19 @@ export function createSrcToOutPathMapper(
} = path): (srcFileName: string) => string {
let srcToOutPath: (srcFileName: string) => string;
if (outDir) {
let path: {} = {}; // Ensure we error if we use `path` instead of `host`.
if (sampleSrcFileName == null || sampleOutFileName == null) {
throw new Error(`Can't calculate the rootDir without a sample srcFileName / outFileName. `);
}
const srcFileDir = host.dirname(sampleSrcFileName).replace(/\\/g, '/');
const outFileDir = host.dirname(sampleOutFileName).replace(/\\/g, '/');
const srcFileDir = normalizeSeparators(host.dirname(sampleSrcFileName));
const outFileDir = normalizeSeparators(host.dirname(sampleOutFileName));
if (srcFileDir === outFileDir) {
return (srcFileName) => srcFileName;
}
// calculate the common suffix, stopping
// at `outDir`.
const srcDirParts = srcFileDir.split('/');
const outDirParts = path.relative(outDir, outFileDir).split('/');
const outDirParts = normalizeSeparators(host.relative(outDir, outFileDir)).split('/');
let i = 0;
while (i < Math.min(srcDirParts.length, outDirParts.length) &&
srcDirParts[srcDirParts.length - 1 - i] === outDirParts[outDirParts.length - 1 - i])
@ -750,7 +760,7 @@ export function createSrcToOutPathMapper(
export function i18nExtract(
formatName: string | null, outFile: string | null, host: ts.CompilerHost,
options: CompilerOptions, bundle: MessageBundle): string[] {
formatName = formatName || 'null';
formatName = formatName || 'xlf';
// Checks the format and returns the extension
const ext = i18nGetExtension(formatName);
const content = i18nSerialize(bundle, formatName, options);
@ -784,7 +794,7 @@ export function i18nSerialize(
}
export function i18nGetExtension(formatName: string): string {
const format = (formatName || 'xlf').toLowerCase();
const format = formatName.toLowerCase();
switch (format) {
case 'xmb':

View File

@ -502,21 +502,23 @@ describe('ngc transformer command-line', () => {
it('should add metadata as decorators', () => {
writeConfig(`{
"extends": "./tsconfig-base.json",
"compilerOptions": {
"emitDecoratorMetadata": true
},
"angularCompilerOptions": {
"annotationsAs": "decorators"
},
"files": ["mymodule.ts"]
}`);
write('aclass.ts', `export class AClass {}`);
write('mymodule.ts', `
import {NgModule, Component} from '@angular/core';
import {NgModule} from '@angular/core';
import {AClass} from './aclass';
@Component({template: ''})
export class MyComp {
fn(p: any) {}
@NgModule({declarations: []})
export class MyModule {
constructor(importedClass: AClass) {}
}
@NgModule({declarations: [MyComp]})
export class MyModule {}
`);
const exitCode = main(['-p', basePath], errorSpy);
@ -524,7 +526,45 @@ describe('ngc transformer command-line', () => {
const mymodulejs = path.resolve(outDir, 'mymodule.js');
const mymoduleSource = fs.readFileSync(mymodulejs, 'utf8');
expect(mymoduleSource).toContain('MyComp = __decorate([');
expect(mymoduleSource).toContain('MyModule = __decorate([');
expect(mymoduleSource).toContain(`import { AClass } from './aclass';`);
expect(mymoduleSource).toContain(`__metadata("design:paramtypes", [AClass])`);
});
it('should add metadata as static fields', () => {
// Note: Don't specify emitDecoratorMetadata here on purpose,
// as regression test for https://github.com/angular/angular/issues/19916.
writeConfig(`{
"extends": "./tsconfig-base.json",
"compilerOptions": {
"emitDecoratorMetadata": false
},
"angularCompilerOptions": {
"annotationsAs": "static fields"
},
"files": ["mymodule.ts"]
}`);
write('aclass.ts', `export class AClass {}`);
write('mymodule.ts', `
import {NgModule} from '@angular/core';
import {AClass} from './aclass';
@NgModule({declarations: []})
export class MyModule {
constructor(importedClass: AClass) {}
}
`);
const exitCode = main(['-p', basePath], errorSpy);
expect(exitCode).toEqual(0);
const mymodulejs = path.resolve(outDir, 'mymodule.js');
const mymoduleSource = fs.readFileSync(mymodulejs, 'utf8');
expect(mymoduleSource).not.toContain('__decorate');
expect(mymoduleSource).toContain('args: [{ declarations: [] },] }');
expect(mymoduleSource).not.toContain(`__metadata`);
expect(mymoduleSource).toContain(`import { AClass } from './aclass';`);
expect(mymoduleSource).toContain(`{ type: AClass, }`);
});
});
@ -1391,5 +1431,41 @@ describe('ngc transformer command-line', () => {
main(['-p', path.join(basePath, 'src/tsconfig.json')], message => messages.push(message));
expect(exitCode).toBe(0, 'Compile failed unexpectedly.\n ' + messages.join('\n '));
});
it('should emit all structural errors', () => {
write('src/tsconfig.json', `{
"extends": "../tsconfig-base.json",
"files": ["test-module.ts"]
}`);
write('src/lib/indirect2.ts', `
declare var f: any;
export const t2 = f\`<p>hello</p>\`;
`);
write('src/lib/indirect1.ts', `
import {t2} from './indirect2';
export const t1 = t2 + ' ';
`);
write('src/lib/test.component.ts', `
import {Component} from '@angular/core';
import {t1} from './indirect1';
@Component({
template: t1
})
export class TestComponent {}
`);
write('src/test-module.ts', `
import {NgModule} from '@angular/core';
import {TestComponent} from './lib/test.component';
@NgModule({declarations: [TestComponent]})
export class TestModule {}
`);
const messages: string[] = [];
const exitCode =
main(['-p', path.join(basePath, 'src/tsconfig.json')], message => messages.push(message));
expect(exitCode).toBe(2, 'Compile was expected to fail');
expect(messages[0]).toContain(['Tagged template expressions are not supported in metadata']);
});
});
});

View File

@ -181,13 +181,15 @@ function convert(annotatedSource: string) {
[fileName], {module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017}, host);
const moduleSourceFile = program.getSourceFile(fileName);
const transformers: ts.CustomTransformers = {
before: [getExpressionLoweringTransformFactory({
before: [getExpressionLoweringTransformFactory(
{
getRequests(sourceFile: ts.SourceFile): RequestLocationMap{
if (sourceFile.fileName == moduleSourceFile.fileName) {
return requests;
} else {return new Map();}
}
})]
},
program)]
};
let result: string = '';
const emitResult = program.emit(

View File

@ -11,7 +11,7 @@ import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import {CompilerHost, LazyRoute} from '../../src/transformers/api';
import {CompilerHost, EmitFlags, LazyRoute} from '../../src/transformers/api';
import {createSrcToOutPathMapper} from '../../src/transformers/program';
import {GENERATED_FILES, StructureIsReused, tsStructureIsReused} from '../../src/transformers/util';
import {TestSupport, expectNoDiagnosticsInProgram, setup} from '../test_support';
@ -309,11 +309,35 @@ describe('ng program', () => {
});
});
it('should typecheck templates even if skipTemplateCodegen is set', () => {
it('should not typecheck templates if skipTemplateCodegen is set but fullTemplateTypeCheck is not',
() => {
testSupport.writeFiles({
'src/main.ts': `
import {NgModule} from '@angular/core';
@NgModule(() => {if (1==1) return null as any;})
export class SomeClassWithInvalidMetadata {}
`,
});
const options = testSupport.createCompilerOptions({skipTemplateCodegen: true});
const host = ng.createCompilerHost({options});
const program = ng.createProgram(
{rootNames: [path.resolve(testSupport.basePath, 'src/main.ts')], options, host});
expectNoDiagnosticsInProgram(options, program);
const emitResult = program.emit({emitFlags: EmitFlags.All});
expect(emitResult.diagnostics.length).toBe(0);
testSupport.shouldExist('built/src/main.metadata.json');
});
it('should typecheck templates if skipTemplateCodegen and fullTemplateTypeCheck is set', () => {
testSupport.writeFiles({
'src/main.ts': createModuleAndCompSource('main', `{{nonExistent}}`),
});
const options = testSupport.createCompilerOptions({skipTemplateCodegen: true});
const options = testSupport.createCompilerOptions({
skipTemplateCodegen: true,
fullTemplateTypeCheck: true,
});
const host = ng.createCompilerHost({options});
const program = ng.createProgram(
{rootNames: [path.resolve(testSupport.basePath, 'src/main.ts')], options, host});
@ -554,8 +578,8 @@ describe('ng program', () => {
});
}
function createProgram(rootNames: string[]) {
const options = testSupport.createCompilerOptions();
function createProgram(rootNames: string[], overrideOptions: ng.CompilerOptions = {}) {
const options = testSupport.createCompilerOptions(overrideOptions);
const host = ng.createCompilerHost({options});
const program = ng.createProgram(
{rootNames: rootNames.map(p => path.resolve(testSupport.basePath, p)), options, host});
@ -797,7 +821,7 @@ describe('ng program', () => {
export class ChildModule {}
`,
});
const program = createProgram(['src/main.ts']).program;
const program = createProgram(['src/main.ts'], {collectAllErrors: true}).program;
expect(normalizeRoutes(program.listLazyRoutes('src/main#MainModule'))).toEqual([{
module: {name: 'MainModule', filePath: path.resolve(testSupport.basePath, 'src/main.ts')},
referencedModule:

View File

@ -54,7 +54,7 @@ export function createAotUrlResolver(host: {
*/
export function createAotCompiler(
compilerHost: AotCompilerHost, options: AotCompilerOptions,
errorCollector: (error: any, type?: any) =>
errorCollector?: (error: any, type?: any) =>
void): {compiler: AotCompiler, reflector: StaticReflector} {
let translations: string = options.translations || '';

View File

@ -6194,9 +6194,9 @@ rx-lite@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
rxjs@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.0.tgz#26d8f3866eb700e247e0728a147c3d628993d812"
rxjs@^5.5.2:
version "5.5.2"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.2.tgz#28d403f0071121967f18ad665563255d54236ac3"
dependencies:
symbol-observable "^1.0.1"