Skip to content

Commit aef4323

Browse files
petebacondarwinmhevery
authored andcommitted
fix(ngcc): use preserve whitespaces from tsconfig if provided (#36189)
Previously ngcc never preserved whitespaces but this is at odds with how the ViewEngine compiler works. In ViewEngine, library templates are recompiled with the current application's tsconfig settings, which meant that whitespace preservation could be set in the application tsconfig file. This commit allows ngcc to use the `preserveWhitespaces` setting from tsconfig when compiling library templates. One should be aware that this disallows different projects with different tsconfig settings to share the same node_modules folder, with regard to whitespace preservation. But this is already the case in the current ngcc since this configuration is hard coded right now. Fixes #35871 PR Close #36189
1 parent fb70083 commit aef4323

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

packages/compiler-cli/ngcc/src/analysis/decoration_analyzer.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import {ConstantPool} from '@angular/compiler';
99
import * as ts from 'typescript';
1010

11+
import {ParsedConfiguration} from '../../..';
1112
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations';
1213
import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles';
1314
import {isFatalDiagnosticError} from '../../../src/ngtsc/diagnostics';
@@ -55,6 +56,7 @@ export class DecorationAnalyzer {
5556
private rootDirs = this.bundle.rootDirs;
5657
private packagePath = this.bundle.entryPoint.package;
5758
private isCore = this.bundle.isCore;
59+
private compilerOptions = this.tsConfig !== null? this.tsConfig.options: {};
5860

5961
moduleResolver =
6062
new ModuleResolver(this.program, this.options, this.host, /* moduleResolutionCache */ null);
@@ -87,7 +89,7 @@ export class DecorationAnalyzer {
8789
new ComponentDecoratorHandler(
8890
this.reflectionHost, this.evaluator, this.fullRegistry, this.fullMetaReader,
8991
this.scopeRegistry, this.scopeRegistry, this.isCore, this.resourceManager, this.rootDirs,
90-
/* defaultPreserveWhitespaces */ false,
92+
!!this.compilerOptions.preserveWhitespaces,
9193
/* i18nUseExternalIds */ true, this.bundle.enableI18nLegacyMessageIdFormat,
9294
this.moduleResolver, this.cycleAnalyzer, this.refEmitter, NOOP_DEFAULT_IMPORT_RECORDER,
9395
NOOP_DEPENDENCY_TRACKER, this.injectableRegistry, /* annotateForClosureCompiler */ false),
@@ -123,7 +125,8 @@ export class DecorationAnalyzer {
123125
constructor(
124126
private fs: FileSystem, private bundle: EntryPointBundle,
125127
private reflectionHost: NgccReflectionHost, private referencesRegistry: ReferencesRegistry,
126-
private diagnosticHandler: (error: ts.Diagnostic) => void = () => {}) {}
128+
private diagnosticHandler: (error: ts.Diagnostic) => void = () => {},
129+
private tsConfig: ParsedConfiguration|null = null) {}
127130

128131
/**
129132
* Analyze a program to find all the decorated files should be transformed.

packages/compiler-cli/ngcc/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ export function mainNgcc(
307307
const createCompileFn: CreateCompileFn = onTaskCompleted => {
308308
const fileWriter = getFileWriter(
309309
fileSystem, logger, pkgJsonUpdater, createNewEntryPointFormats, errorOnFailedEntryPoint);
310-
const transformer = new Transformer(fileSystem, logger);
310+
const transformer = new Transformer(fileSystem, logger, tsConfig);
311311

312312
return (task: Task) => {
313313
const {entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts} = task;

packages/compiler-cli/ngcc/src/packages/transformer.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
import * as ts from 'typescript';
99

10+
import {ParsedConfiguration} from '../../..';
1011
import {FileSystem} from '../../../src/ngtsc/file_system';
1112
import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection';
1213
import {DecorationAnalyzer} from '../analysis/decoration_analyzer';
@@ -63,7 +64,9 @@ export type TransformResult = {
6364
* - Some formats may contain multiple "modules" in a single file.
6465
*/
6566
export class Transformer {
66-
constructor(private fs: FileSystem, private logger: Logger) {}
67+
constructor(
68+
private fs: FileSystem, private logger: Logger,
69+
private tsConfig: ParsedConfiguration|null = null) {}
6770

6871
/**
6972
* Transform the source (and typings) files of a bundle.
@@ -146,7 +149,7 @@ export class Transformer {
146149
const diagnostics: ts.Diagnostic[] = [];
147150
const decorationAnalyzer = new DecorationAnalyzer(
148151
this.fs, bundle, reflectionHost, referencesRegistry,
149-
diagnostic => diagnostics.push(diagnostic));
152+
diagnostic => diagnostics.push(diagnostic), this.tsConfig);
150153
const decorationAnalyses = decorationAnalyzer.analyzeProgram();
151154

152155
const moduleWithProvidersAnalyzer =

packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,44 @@ runInEachFileSystem(() => {
13731373
});
13741374
});
13751375

1376+
describe('whitespace preservation', () => {
1377+
it('should default not to preserve whitespace', () => {
1378+
mainNgcc({basePath: '/dist', propertiesToConsider: ['es2015']});
1379+
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
1380+
es2015: '0.0.0-PLACEHOLDER',
1381+
typings: '0.0.0-PLACEHOLDER',
1382+
});
1383+
expect(fs.readFile(_('/dist/local-package/index.js')))
1384+
.toMatch(/ɵɵtext\(\d+, " Hello\\n"\);/);
1385+
});
1386+
1387+
it('should preserve whitespace if set in a loaded tsconfig.json', () => {
1388+
fs.writeFile(
1389+
_('/tsconfig.json'),
1390+
JSON.stringify({angularCompilerOptions: {preserveWhitespaces: true}}));
1391+
mainNgcc({basePath: '/dist', propertiesToConsider: ['es2015']});
1392+
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
1393+
es2015: '0.0.0-PLACEHOLDER',
1394+
typings: '0.0.0-PLACEHOLDER',
1395+
});
1396+
expect(fs.readFile(_('/dist/local-package/index.js')))
1397+
.toMatch(/ɵɵtext\(\d+, "\\n Hello\\n"\);/);
1398+
});
1399+
1400+
it('should not preserve whitespace if set to false in a loaded tsconfig.json', () => {
1401+
fs.writeFile(
1402+
_('/tsconfig.json'),
1403+
JSON.stringify({angularCompilerOptions: {preserveWhitespaces: false}}));
1404+
mainNgcc({basePath: '/dist', propertiesToConsider: ['es2015']});
1405+
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
1406+
es2015: '0.0.0-PLACEHOLDER',
1407+
typings: '0.0.0-PLACEHOLDER',
1408+
});
1409+
expect(fs.readFile(_('/dist/local-package/index.js')))
1410+
.toMatch(/ɵɵtext\(\d+, " Hello\\n"\);/);
1411+
});
1412+
});
1413+
13761414
describe('with configuration files', () => {
13771415
it('should process a configured deep-import as an entry-point', () => {
13781416
loadTestFiles([
@@ -1883,7 +1921,7 @@ runInEachFileSystem(() => {
18831921
{
18841922
name: _('/dist/local-package/index.js'),
18851923
contents:
1886-
`import {Component} from '@angular/core';\nexport class AppComponent {};\nAppComponent.decorators = [\n{ type: Component, args: [{selector: 'app', template: '<h2>Hello</h2>'}] }\n];`
1924+
`import {Component} from '@angular/core';\nexport class AppComponent {};\nAppComponent.decorators = [\n{ type: Component, args: [{selector: 'app', template: '<h2>\\n Hello\\n</h2>'}] }\n];`
18871925
},
18881926
{
18891927
name: _('/dist/local-package/index.d.ts'),

0 commit comments

Comments
 (0)