Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions projects/igniteui-angular/migrations/common/tsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,25 @@ import { Logger } from './tsLogger';
import { TSLanguageService } from './tsPlugin/TSLanguageService';

export const IG_PACKAGE_NAME = 'igniteui-angular';
export const IG_LICENSED_PACKAGE_NAME = '@infragistics/igniteui-angular';
export const NG_LANG_SERVICE_PACKAGE_NAME = '@angular/language-service';
export const NG_CORE_PACKAGE_NAME = '@angular/core';
export const CUSTOM_TS_PLUGIN_PATH = './tsPlugin';
export const CUSTOM_TS_PLUGIN_NAME = 'igx-ts-plugin';

/**
* Checks if the given import path is from igniteui-angular package.
* Handles both OSS (igniteui-angular) and licensed (@infragistics/igniteui-angular) versions,
* as well as subpaths (e.g., igniteui-angular/core, @infragistics/igniteui-angular/grids).
* @param importPath The module specifier text to check
* @returns true if the import path is from igniteui-angular package
*/
export const isIgniteuiImport = (importPath: string): boolean =>
importPath === IG_PACKAGE_NAME ||
importPath === IG_LICENSED_PACKAGE_NAME ||
importPath.startsWith(`${IG_PACKAGE_NAME}/`) ||
importPath.startsWith(`${IG_LICENSED_PACKAGE_NAME}/`);

enum SyntaxTokens {
ClosingParenthesis = ')',
MemberAccess = '.',
Expand Down Expand Up @@ -83,13 +97,13 @@ export const getImportModulePositions = (sourceText: string, startsWith: string)
return positions;
};

/** Filters out statements to named imports (e.g. `import {x, y}`) from PACKAGE_IMPORT */
export const namedImportFilter = (statement: ts.Statement) => {
if (statement.kind === ts.SyntaxKind.ImportDeclaration &&
((statement as ts.ImportDeclaration).moduleSpecifier as ts.StringLiteral).text.endsWith(IG_PACKAGE_NAME)) {

const clause = (statement as ts.ImportDeclaration).importClause;
return clause && clause.namedBindings && clause.namedBindings.kind === ts.SyntaxKind.NamedImports;
/** Filters out statements to named imports (e.g. `import {x, y}`) from IG_PACKAGE_NAME */
export const igNamedImportFilter = (
statement: ts.Statement,
): statement is ts.ImportDeclaration & { moduleSpecifier: ts.StringLiteral } & { importClause: { namedBindings: ts.NamedImports } } => {
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier) && isIgniteuiImport(statement.moduleSpecifier.text)) {
const clause = statement.importClause;
return clause?.namedBindings && clause.namedBindings.kind === ts.SyntaxKind.NamedImports;
}
return false;
};
Expand All @@ -100,14 +114,13 @@ export const getRenamePositions = (sourcePath: string, name: string, service: ts
const source = service.getProgram().getSourceFile(sourcePath);
const positions = [];

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const imports = source.statements.filter(<(a: ts.Statement) => a is ts.ImportDeclaration>namedImportFilter);
const imports = source.statements.filter(igNamedImportFilter);
if (!imports.length) {
return positions;
}
const elements: ts.NodeArray<ts.ImportSpecifier> =
imports
.map(x => (x.importClause.namedBindings as ts.NamedImports).elements)
.map(x => x.importClause.namedBindings.elements)
.reduce((prev, current) => prev.concat(current) as unknown as ts.NodeArray<ts.ImportSpecifier>);

for (const elem of elements) {
Expand Down
4 changes: 2 additions & 2 deletions projects/igniteui-angular/migrations/update-17_0_0/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as ts from 'typescript';
import { UpdateChanges } from '../common/UpdateChanges';
// use bare specifier to escape the schematics encapsulation for the dynamic import:
import { nativeImport } from 'igniteui-angular/migrations/common/import-helper.js';
import { namedImportFilter } from '../common/tsUtils';
import { igNamedImportFilter } from '../common/tsUtils';
import { FileChange, findElementNodes, getAttribute, getSourceOffset, hasAttribute, parseFile } from '../common/util';

const version = '17.0.0';
Expand Down Expand Up @@ -95,7 +95,7 @@ export default (): Rule => async (host: Tree, context: SchematicContext) => {
var fileContent = host.read(filePath).toString();

const source = ts.createSourceFile('', fileContent, ts.ScriptTarget.Latest, true)
const igImports = source.statements.filter(<(a: ts.Statement) => a is ts.ImportDeclaration>namedImportFilter);
const igImports = source.statements.filter(igNamedImportFilter);

// Find all animations imported from 'igniteui-angular' and delete them.
for (const igImport of igImports) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
Tree
} from '@angular-devkit/schematics';
import * as ts from 'typescript';
import { IG_PACKAGE_NAME, IG_LICENSED_PACKAGE_NAME, igNamedImportFilter } from '../common/tsUtils';

const version = '21.0.0';

Expand Down Expand Up @@ -711,31 +712,17 @@ const TYPE_RENAMES = new Map<string, { newName: string, entryPoint: string }>([
]);

function migrateImportDeclaration(node: ts.ImportDeclaration, sourceFile: ts.SourceFile): { start: number, end: number, replacement: string } | null {
const moduleSpecifier = node.moduleSpecifier;
if (!ts.isStringLiteral(moduleSpecifier)) {
if (!igNamedImportFilter(node)) {
return null;
}

const importPath = moduleSpecifier.text;

// Only process igniteui-angular imports (not already using entry points)
if (importPath !== 'igniteui-angular' && importPath !== '@infragistics/igniteui-angular') {
return null;
}

const importClause = node.importClause;
if (!importClause || !importClause.namedBindings) {
return null;
}

if (!ts.isNamedImports(importClause.namedBindings)) {
return null;
}
const importPath = node.moduleSpecifier.text;
const namedBindings = node.importClause.namedBindings;

// Group imports by entry point
const entryPointGroups = new Map<string, string[]>();

for (const element of importClause.namedBindings.elements) {
for (const element of namedBindings.elements) {
const name = element.name.text;
const alias = element.propertyName?.text;
const importName = alias || name;
Expand Down Expand Up @@ -800,7 +787,7 @@ function migrateFile(filePath: string, content: string): string {

// Track old type names that were imported
const moduleSpecifier = node.moduleSpecifier;
if (ts.isStringLiteral(moduleSpecifier) && (moduleSpecifier.text === 'igniteui-angular' || moduleSpecifier.text === '@infragistics/igniteui-angular')) {
if (ts.isStringLiteral(moduleSpecifier) && (moduleSpecifier.text === IG_PACKAGE_NAME || moduleSpecifier.text === IG_LICENSED_PACKAGE_NAME)) {
const importClause = node.importClause;
if (importClause?.namedBindings && ts.isNamedImports(importClause.namedBindings)) {
for (const element of importClause.namedBindings.elements) {
Expand Down Expand Up @@ -877,9 +864,9 @@ export default function migrate(): Rule {

const originalContent = content.toString();

// Check if file has igniteui-angular imports
if (!originalContent.includes("from 'igniteui-angular'") && !originalContent.includes('from "igniteui-angular"') &&
!originalContent.includes("from '@infragistics/igniteui-angular'") && !originalContent.includes('from "@infragistics/igniteui-angular"')) {
// Check if file has base igniteui-angular imports
if (!originalContent.includes(`from '${IG_PACKAGE_NAME}'`) && !originalContent.includes(`from "${IG_PACKAGE_NAME}"`) &&
!originalContent.includes(`from '${IG_LICENSED_PACKAGE_NAME}'`) && !originalContent.includes(`from "${IG_LICENSED_PACKAGE_NAME}"`)) {
return;
}

Expand Down
Loading