Skip to content

Commit cadcf11

Browse files
committed
Merge branch '16.1.x' of https://github.com/IgniteUI/igniteui-angular into simeonoff/sass-build
2 parents 4c8de07 + 721dc79 commit cadcf11

File tree

12 files changed

+3755
-2753
lines changed

12 files changed

+3755
-2753
lines changed

package-lock.json

Lines changed: 3617 additions & 2693 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"fflate": "^0.7.3",
6969
"hammerjs": "^2.0.8",
7070
"igniteui-theming": "^3.1.1",
71-
"igniteui-trial-watermark": "^2.0.0",
71+
"igniteui-trial-watermark": "^3.0.2",
7272
"lodash-es": "^4.17.21",
7373
"rxjs": "^6.6.7",
7474
"tslib": "^2.3.0",

projects/igniteui-angular/migrations/common/ServerHost.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ export class ServerHost implements ts.server.ServerHost {
4747
public watchFile(_path: string, _callback: ts.FileWatcherCallback, _pollingInterval?: number):
4848
ts.FileWatcher {
4949
// return ts.sys.watchFile(path, callback, pollingInterval);
50-
return undefined;
50+
return { close: () => {} };
5151
}
5252

5353
public watchDirectory(_path: string, _callback: ts.DirectoryWatcherCallback, _recursive?: boolean):
5454
ts.FileWatcher {
5555
// return ts.sys.watchDirectory(path, callback, recursive);
56-
return undefined;
56+
return { close: () => {} };
5757
}
5858
//#endregion
5959

@@ -106,7 +106,7 @@ export class ServerHost implements ts.server.ServerHost {
106106
// check directory contents in Tree (w/ relative paths)
107107
path = pathFs.relative(this.getCurrentDirectory(), path);
108108
// return directory contents w/ absolute paths for LS
109-
return this.host.getDir(path).subdirs.map(e => pathFs.resolve(e));
109+
return this.host.getDir(path).subdirs.map(e => pathFs.resolve(path, e));
110110
}
111111

112112
/**
@@ -116,7 +116,7 @@ export class ServerHost implements ts.server.ServerHost {
116116
// check directory contents in Tree (w/ relative paths)
117117
path = pathFs.relative(this.getCurrentDirectory(), path);
118118
// return directory contents w/ absolute paths for LS
119-
return this.host.getDir(path).subfiles.map(e => pathFs.resolve(e));
119+
return this.host.getDir(path).subfiles.map(e => pathFs.resolve(path, e));
120120
}
121121

122122
public require(initialPath: string, moduleName: string) {

projects/igniteui-angular/migrations/common/UpdateChanges.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import * as ts from 'typescript';
44
import * as tss from 'typescript/lib/tsserverlibrary';
55
import { SchematicContext, Tree, FileVisitor } from '@angular-devkit/schematics';
6-
import { WorkspaceSchema, WorkspaceProject, ProjectType } from '@schematics/angular/utility/workspace-models';
6+
import type { WorkspaceSchema } from '@schematics/angular/utility/workspace-models';
77
import {
88
ClassChanges, BindingChanges, SelectorChange,
99
SelectorChanges, ThemeChanges, ImportsChanges, MemberChanges, ThemeChange, ThemeType
@@ -59,13 +59,13 @@ export class UpdateChanges {
5959
// Force Angular service to compile project on initial load w/ configure project
6060
// otherwise if the first compilation occurs on an HTML file the project won't have proper refs
6161
// and no actual angular metadata will be resolved for the rest of the migration
62-
const wsProject = this.resolveWorkspaceProject();
63-
if (!wsProject) {
62+
63+
// TODO: this patter/issue might be obsolete; if so, should be safe to return _projectService directly
64+
const mainRelPath = this.getWorkspaceProjectEntryPath();
65+
if (!mainRelPath) {
6466
return null;
6567
}
66-
const mainRelPath = wsProject.architect?.build?.options['main'] ?
67-
path.join(wsProject.root, wsProject.architect?.build?.options['main']) :
68-
`src/main.ts`;
68+
6969
// patch TSConfig so it includes angularOptions.strictTemplates
7070
// ivy ls requires this in order to function properly on templates
7171
this.patchTsConfig();
@@ -74,8 +74,14 @@ export class UpdateChanges {
7474
this._projectService.openClientFile(scriptInfo.fileName);
7575

7676

77-
const project = this._projectService.findProject(scriptInfo.containingProjects[0].projectName);
78-
project.getLanguageService().getSemanticDiagnostics(mainAbsPath);
77+
try {
78+
const project = this._projectService.findProject(scriptInfo.containingProjects[0].projectName);
79+
project.getLanguageService().getSemanticDiagnostics(mainAbsPath);
80+
} catch (err) {
81+
this.context.logger.warn(
82+
"An error occurred during TypeScript project service setup. Some migrations relying on language services might not be applied."
83+
);
84+
}
7985
}
8086

8187
return this._projectService;
@@ -829,22 +835,26 @@ export class UpdateChanges {
829835
return project;
830836
}
831837

832-
private resolveWorkspaceProject(): WorkspaceProject<ProjectType> | null {
833-
let wsProject = this.workspace.projects[0];
834-
if (!wsProject) {
835-
const projectKeys = Object.keys(this.workspace.projects);
836-
if (!projectKeys.length) {
837-
this.context
838-
.logger
839-
.info(
838+
private getWorkspaceProjectEntryPath(): string | null {
839+
const projectKeys = Object.keys(this.workspace.projects);
840+
if (!projectKeys.length) {
841+
this.context.logger.info(
840842
`Could not resolve project from directory ${this.serverHost.getCurrentDirectory()}. Some migrations may not be applied.`);
841-
return null;
843+
return null;
844+
}
845+
846+
// grab the first possible main path:
847+
for (const key of projectKeys) {
848+
const wsProject = this.workspace.projects[key];
849+
// intentionally compare against string values of the enum to avoid hard import
850+
if (wsProject.projectType == "application" && wsProject.architect?.build?.options['main']) {
851+
return wsProject.architect.build.options['main'];
852+
} else if (wsProject.projectType == "library") {
853+
// TODO: attempt to resolve from project ng-package.json or tsConfig
842854
}
843-
// get the first configured project in the workspace
844-
wsProject = this.workspace.projects[projectKeys[0]];
845855
}
846856

847-
return wsProject;
857+
return null;
848858
}
849859
}
850860

projects/igniteui-angular/migrations/common/tsUtils.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,12 @@ const getTypeDefinitions = (langServ: tss.LanguageService, entryPath: string, po
260260
*/
261261
export const getTypeDefinitionAtPosition =
262262
(langServ: tss.LanguageService, entryPath: string, position: number): MemberInfo | null => {
263-
const definition = langServ.getDefinitionAndBoundSpan(entryPath, position)?.definitions[0];
263+
let definition;
264+
try {
265+
definition = langServ.getDefinitionAndBoundSpan(entryPath, position)?.definitions[0];
266+
} catch (err) {
267+
return null;
268+
}
264269
if (!definition) {
265270
return null;
266271
}
@@ -352,7 +357,12 @@ export const isMemberIgniteUI =
352357
matchPosition = langServ.getBraceMatchingAtPosition(entryPath, matchPosition - 1)[0]?.start ?? matchPosition;
353358
}
354359

355-
const typeDef = getTypeDefinitionAtPosition(langServ, entryPath, matchPosition);
360+
let typeDef;
361+
try {
362+
typeDef = getTypeDefinitionAtPosition(langServ, entryPath, matchPosition);
363+
} catch (err) {
364+
false;
365+
}
356366
if (!typeDef) {
357367
return false;
358368
}

projects/igniteui-angular/migrations/common/util.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { WorkspaceSchema, WorkspaceProject } from '@schematics/angular/utility/w
55
import { execSync } from 'child_process';
66
import {
77
Attribute,
8+
Block,
9+
BlockGroup,
10+
BlockParameter,
811
Comment,
912
Element,
1013
Expansion,
@@ -245,10 +248,10 @@ class SerializerVisitor implements Visitor {
245248

246249
public visitElement(element: Element, _context: any): any {
247250
if (this.getHtmlTagDefinition(element.name).isVoid) {
248-
return `<${element.name}${this._visitAll(element.attrs, ' ')}/>`;
251+
return `<${element.name}${this._visitAll(element.attrs, ' ', ' ')}/>`;
249252
}
250253

251-
return `<${element.name}${this._visitAll(element.attrs, ' ')}>${this._visitAll(element.children)}</${element.name}>`;
254+
return `<${element.name}${this._visitAll(element.attrs, ' ', ' ')}>${this._visitAll(element.children)}</${element.name}>`;
252255
}
253256

254257
public visitAttribute(attribute: Attribute, _context: any): any {
@@ -271,11 +274,21 @@ class SerializerVisitor implements Visitor {
271274
return ` ${expansionCase.value} {${this._visitAll(expansionCase.expression)}}`;
272275
}
273276

274-
private _visitAll(nodes: Node[], join = ''): string {
275-
if (nodes.length === 0) {
276-
return '';
277-
}
278-
return join + nodes.map(a => a.visit(this, null)).join(join);
277+
public visitBlock(block: Block, _context: any) {
278+
const params =
279+
block.parameters.length === 0 ? ' ' : ` (${this._visitAll(block.parameters, ';', ' ')}) `;
280+
return `@${block.name}${params}{${this._visitAll(block.children)}}`;
281+
}
282+
283+
public visitBlockParameter(parameter: BlockParameter, _context: any) {
284+
return parameter.expression;
285+
}
286+
287+
// XXX: This **HAS** to be removed in the next major release of Angular (v17) as it will error out again
288+
public visitBlockGroup(_group: BlockGroup, _context: any) { }
289+
290+
private _visitAll(nodes: Node[], separator = '', prefix = ''): string {
291+
return nodes.length > 0 ? prefix + nodes.map(a => a.visit(this, null)).join(separator) : '';
279292
}
280293
}
281294

@@ -286,7 +299,7 @@ export const serializeNodes = (nodes: Node[], getHtmlTagDefinition: (tagName: st
286299

287300
export const makeNgIf = (name: string, value: string) => name.startsWith('[') && value !== 'true';
288301

289-
export const stringifyAttriutes = (attributes: Attribute[]) => {
302+
export const stringifyAttributes = (attributes: Attribute[]) => {
290303
let stringAttributes = '';
291304
attributes.forEach(element => {
292305
// eslint-disable-next-line max-len

projects/igniteui-angular/migrations/update-12_1_0/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Element } from '@angular/compiler';
22
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
33
import { UpdateChanges } from '../common/UpdateChanges';
4-
import { FileChange, findElementNodes, getAttribute, getSourceOffset, hasAttribute, parseFile,
5-
serializeNodes, makeNgIf, stringifyAttriutes } from '../common/util';
4+
import {
5+
FileChange, findElementNodes, getAttribute, getSourceOffset, hasAttribute, parseFile,
6+
serializeNodes, makeNgIf, stringifyAttributes
7+
} from '../common/util';
68
import { nativeImport } from '../common/import-helper.js';
79

810
const version = '12.1.0';
@@ -19,7 +21,7 @@ export default (): Rule => async (host: Tree, context: SchematicContext) => {
1921
const warnMsg = `\n<!-- Auto migrated template content. Please, check your bindings! -->\n`;
2022
const deprecatedToken = 'IgxGridTransaction';
2123
const providerWarnMsg = `/* Injection token 'IgxGridTransaction' has been deprecated. ` +
22-
`Please refer to the update guide for more details. */`;
24+
`Please refer to the update guide for more details. */`;
2325
const templateNames = [];
2426

2527
const applyChanges = () => {
@@ -64,7 +66,7 @@ export default (): Rule => async (host: Tree, context: SchematicContext) => {
6466
const paginatorTemplate = ngTemplates.filter(template => hasAttribute(template as Element, `#${paginationTemplateName?.value}`))[0];
6567
if (paginatorTemplate && checkForPaginatorInTemplate(path, paginationTemplateName?.value)) {
6668
const pgCmpt = findElementNodes((paginatorTemplate as Element).children, 'igx-paginator')[0];
67-
return `\n<igx-paginator${isChildGrid ? ' *igxPaginator' : ''}${stringifyAttriutes((pgCmpt as Element).attrs)}></igx-paginator>`;
69+
return `\n<igx-paginator${isChildGrid ? ' *igxPaginator' : ''}${stringifyAttributes((pgCmpt as Element).attrs)}></igx-paginator>`;
6870
} else {
6971
// eslint-disable-next-line max-len
7072
return `\n<igx-paginator${isChildGrid ? ' *igxPaginator' : ''}${makeNgIf(propName, value) ? ` *ngIf="${value}"` : ''}>${moveTemplate(paginatorTemplate)}</igx-paginator>`;

projects/igniteui-angular/migrations/update-16_1_0/index.spec.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe(`Update to ${version}`, () => {
4747
public title: IgxStepSubTitleDirective;
4848
}
4949
`);
50-
const tree = await schematicRunner.runSchematicAsync(migrationName, { shouldInvokeLS: false }, appTree).toPromise();
50+
const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
5151

5252
const expectedContent = `import { Component, ViewChild } from '@angular/core';
5353
import { IgxStepSubtitleDirective } from 'igniteui-angular';
@@ -72,18 +72,18 @@ describe(`Update to ${version}`, () => {
7272
`<igx-stepper>
7373
<igx-step>
7474
<p igxStepTitle>Home</p>
75-
<p igxStepSubTitle>Home Sub Title</p>
75+
<p igxStepSubTitle>Home Sub Title</p>
7676
</igx-step>
7777
</igx-stepper>`);
7878

79-
const tree = await schematicRunner.runSchematicAsync(migrationName, {}, appTree)
80-
.toPromise();
79+
const tree = await schematicRunner.runSchematic(migrationName, {}, appTree);
80+
8181
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html'))
8282
.toEqual(
8383
`<igx-stepper>
8484
<igx-step>
8585
<p igxStepTitle>Home</p>
86-
<p igxStepSubtitle>Home Sub Title</p>
86+
<p igxStepSubtitle>Home Sub Title</p>
8787
</igx-step>
8888
</igx-stepper>`);
8989

@@ -108,9 +108,7 @@ describe(`Update to ${version}`, () => {
108108
}
109109
`);
110110

111-
const tree = await schematicRunner
112-
.runSchematicAsync(migrationName, {}, appTree)
113-
.toPromise();
111+
const tree = await schematicRunner.runSchematic(migrationName, {}, appTree);
114112

115113
expect(
116114
tree.readContent('/testSrc/appPrefix/component/test.component.ts')
@@ -133,7 +131,7 @@ describe(`Update to ${version}`, () => {
133131
);
134132
});
135133

136-
it('Should remove multiSelection property set to "true" and replace it with selectionMode property set to "multi"', async () => {
134+
it('Should remove button-group multiSelection property set to "true" and replace it with selectionMode property set to "multi"', async () => {
137135
appTree.create(
138136
`/testSrc/appPrefix/component/test.component.html`,
139137
`<igx-buttongroup [multiSelection]="true">
@@ -145,9 +143,8 @@ describe(`Update to ${version}`, () => {
145143
</button>
146144
</igx-buttongroup>`);
147145

148-
const tree = await schematicRunner.runSchematicAsync(migrationName, {}, appTree)
149-
.toPromise();
150-
146+
const tree = await schematicRunner.runSchematic(migrationName, {}, appTree);
147+
151148
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html'))
152149
.toEqual(
153150
`<igx-buttongroup [selectionMode]="'multi'">
@@ -160,7 +157,7 @@ describe(`Update to ${version}`, () => {
160157
</igx-buttongroup>`);
161158
});
162159

163-
it('Should remove multiSelection property set to "false"', async () => {
160+
it('Should remove button-group multiSelection property set to "false"', async () => {
164161
appTree.create(
165162
'/testSrc/appPrefix/component/test.component.html',
166163
`<igx-buttongroup [multiSelection]="false">
@@ -172,8 +169,7 @@ describe(`Update to ${version}`, () => {
172169
</button>
173170
</igx-buttongroup>`);
174171

175-
const tree = await schematicRunner.runSchematicAsync(migrationName, {}, appTree)
176-
.toPromise();
172+
const tree = await schematicRunner.runSchematic(migrationName, {}, appTree);
177173

178174
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html'))
179175
.toEqual(
@@ -186,4 +182,26 @@ describe(`Update to ${version}`, () => {
186182
</button>
187183
</igx-buttongroup>`);
188184
});
185+
186+
it('Should not update button-group without multiSelection prop', async () => {
187+
const content = `<igx-buttongroup alignment="horizontal">
188+
<button igxButton>
189+
Button 1
190+
</button>
191+
<button igxButton>
192+
Button 2
193+
</button>
194+
</igx-buttongroup>
195+
<igx-buttongroup>
196+
<button igxButton>
197+
Button 1
198+
</button>
199+
</igx-buttongroup>`;
200+
201+
appTree.create(`/testSrc/appPrefix/component/test.component.html`, content);
202+
203+
const tree = await schematicRunner.runSchematic(migrationName, {}, appTree);
204+
205+
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(content);
206+
});
189207
});

projects/igniteui-angular/migrations/update-16_1_0/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
Tree
55
} from '@angular-devkit/schematics';
66
import { UpdateChanges } from '../common/UpdateChanges';
7-
import { FileChange, findElementNodes, getAttribute, getSourceOffset, parseFile } from '../common/util';
7+
import { FileChange, findElementNodes, getAttribute, getSourceOffset, hasAttribute, parseFile } from '../common/util';
88
import { nativeImport } from '../common/import-helper.js';
99
import { Element } from '@angular/compiler';
1010

@@ -23,11 +23,11 @@ export default (): Rule => async (host: Tree, context: SchematicContext) => {
2323
const applyChanges = () => {
2424
for (const [path, change] of changes.entries()) {
2525
let buffer = host.read(path).toString();
26-
26+
2727
change.sort((c, c1) => c.position - c1.position)
2828
.reverse()
2929
.forEach(c => buffer = c.apply(buffer));
30-
30+
3131
host.overwrite(path, buffer);
3232
}
3333
};
@@ -42,7 +42,9 @@ export default (): Rule => async (host: Tree, context: SchematicContext) => {
4242

4343
for (const path of update.templateFiles) {
4444
const buttonGroups = findElementNodes(parseFile(new HtmlParser(), host, path), 'igx-buttongroup');
45-
buttonGroups.map(node => getSourceOffset(node as Element))
45+
buttonGroups
46+
.filter(node => hasAttribute(node as Element, prop))
47+
.map(node => getSourceOffset(node as Element))
4648
.forEach(offset => {
4749
const { startTag, file, node } = offset;
4850
const { name, value } = getAttribute(node, prop)[0];

projects/igniteui-angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
"hammerjs": "^2.0.8",
7474
"fflate": "^0.7.3",
7575
"tslib": "^2.3.0",
76-
"igniteui-trial-watermark": "^1.0.3",
76+
"igniteui-trial-watermark": "^3.0.2",
7777
"lodash-es": "^4.17.21",
7878
"uuid": "^9.0.0",
7979
"igniteui-theming": "^3.1.1",

0 commit comments

Comments
 (0)