diff --git a/projects/igniteui-angular/migrations/common/tsUtils.ts b/projects/igniteui-angular/migrations/common/tsUtils.ts index 1c74a906bdd..9a03e7987b6 100644 --- a/projects/igniteui-angular/migrations/common/tsUtils.ts +++ b/projects/igniteui-angular/migrations/common/tsUtils.ts @@ -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 = '.', @@ -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; }; @@ -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 = 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); for (const elem of elements) { diff --git a/projects/igniteui-angular/migrations/update-17_0_0/index.ts b/projects/igniteui-angular/migrations/update-17_0_0/index.ts index fc63c790366..2dd2d32ca63 100644 --- a/projects/igniteui-angular/migrations/update-17_0_0/index.ts +++ b/projects/igniteui-angular/migrations/update-17_0_0/index.ts @@ -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'; @@ -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) { diff --git a/projects/igniteui-angular/migrations/update-21_0_0_import-migration/index.ts b/projects/igniteui-angular/migrations/update-21_0_0_import-migration/index.ts index d112103eaa8..6dba3a67e1a 100644 --- a/projects/igniteui-angular/migrations/update-21_0_0_import-migration/index.ts +++ b/projects/igniteui-angular/migrations/update-21_0_0_import-migration/index.ts @@ -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'; @@ -711,31 +712,17 @@ const TYPE_RENAMES = new Map([ ]); 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(); - 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; @@ -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) { @@ -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; }