mirror of
https://github.com/danielsogl/awesome-cordova-plugins.git
synced 2026-05-02 00:07:23 +08:00
fix: add strict types to build scripts and remove all any usage
Replace all implicit and explicit any types in build scripts with proper TypeScript Compiler API types (Decorator, ClassDeclaration, MethodDeclaration, Identifier, SourceFile, etc.). Add PackageJson and InjectableClassEntry interfaces. Fix return types, null checks, and type assertions throughout all transformer scripts.
This commit is contained in:
@@ -23,7 +23,7 @@ export const EMIT_PATH = resolve(ROOT, 'injectable-classes.json');
|
||||
*/
|
||||
export function extractInjectables() {
|
||||
return (ctx: TransformationContext) => {
|
||||
return (tsSourceFile) => {
|
||||
return (tsSourceFile: any) => {
|
||||
if (tsSourceFile.fileName.indexOf('src/@awesome-cordova-plugins/plugins') > -1) {
|
||||
visitEachChild(
|
||||
tsSourceFile,
|
||||
@@ -36,7 +36,7 @@ export function extractInjectables() {
|
||||
if (isInjectable) {
|
||||
injectableClasses.push({
|
||||
file: tsSourceFile.path,
|
||||
className: (node as ClassDeclaration).name.text,
|
||||
className: (node as ClassDeclaration).name!.text,
|
||||
dirName: tsSourceFile.path.split(/[\\\/]+/).reverse()[1],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import { factory, SourceFile, SyntaxKind, TransformationContext } from 'typescript';
|
||||
import { factory, Identifier, ImportSpecifier, SourceFile, SyntaxKind, TransformationContext } from 'typescript';
|
||||
|
||||
import { getMethodsForDecorator } from '../helpers';
|
||||
|
||||
function transformImports(file: SourceFile, ctx: TransformationContext, ngcBuild?: boolean) {
|
||||
function transformImports(file: SourceFile, _ctx: TransformationContext, ngcBuild?: boolean) {
|
||||
// remove angular imports
|
||||
if (!ngcBuild) {
|
||||
// @ts-expect-error
|
||||
file.statements = (file.statements as any).filter(
|
||||
(s: any) => !(s.kind === SyntaxKind.ImportDeclaration && s.moduleSpecifier.text === '@angular/core')
|
||||
);
|
||||
// @ts-expect-error — mutating readonly statements for transformer pipeline
|
||||
file.statements = (
|
||||
file.statements as unknown as Array<{ kind: number; moduleSpecifier?: { text: string } }>
|
||||
).filter((s) => !(s.kind === SyntaxKind.ImportDeclaration && s.moduleSpecifier?.text === '@angular/core'));
|
||||
}
|
||||
|
||||
// find the @awesome-cordova-plugins/core import statement
|
||||
const importStatement = (file.statements as any).find((s: any) => {
|
||||
return s.kind === SyntaxKind.ImportDeclaration && s.moduleSpecifier.text === '@awesome-cordova-plugins/core';
|
||||
});
|
||||
const importStatement = (file.statements as unknown as Array<Record<string, unknown>>).find((s) => {
|
||||
return (
|
||||
(s as { kind: number }).kind === SyntaxKind.ImportDeclaration &&
|
||||
(s as { moduleSpecifier: { text: string } }).moduleSpecifier.text === '@awesome-cordova-plugins/core'
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
}) as Record<string, any> | undefined;
|
||||
|
||||
// we're only interested in files containing @awesome-cordova-plugins/core import statement
|
||||
if (!importStatement) return file;
|
||||
@@ -27,7 +31,7 @@ function transformImports(file: SourceFile, ctx: TransformationContext, ngcBuild
|
||||
|
||||
const keep: string[] = ['getPromise', 'checkAvailability'];
|
||||
|
||||
let m;
|
||||
let m: RegExpExecArray | null;
|
||||
|
||||
while ((m = decoratorRegex.exec(file.text)) !== null) {
|
||||
if (m.index === decoratorRegex.lastIndex) {
|
||||
@@ -37,27 +41,27 @@ function transformImports(file: SourceFile, ctx: TransformationContext, ngcBuild
|
||||
}
|
||||
|
||||
if (decorators.length) {
|
||||
let methods = [];
|
||||
let methods: string[] = [];
|
||||
|
||||
decorators.forEach((d) => (methods = getMethodsForDecorator(d).concat(methods)));
|
||||
|
||||
const methodElements = methods.map((m) => factory.createIdentifier(m));
|
||||
const methodNames = methodElements.map((el) => el.escapedText);
|
||||
const methodElements = methods.map((name: string) => factory.createIdentifier(name));
|
||||
const methodNames = methodElements.map((el: Identifier) => el.escapedText);
|
||||
|
||||
importStatement.importClause.namedBindings.elements = [
|
||||
factory.createIdentifier('AwesomeCordovaNativePlugin'),
|
||||
...methodElements,
|
||||
...importStatement.importClause.namedBindings.elements.filter(
|
||||
(el) => keep.indexOf(el.name.text) !== -1 && methodNames.indexOf(el.name.text) === -1
|
||||
(el: ImportSpecifier) => keep.indexOf(el.name.text) !== -1 && methodNames.indexOf(el.name.text) === -1
|
||||
),
|
||||
];
|
||||
|
||||
if (ngcBuild) {
|
||||
importStatement.importClause.namedBindings.elements = importStatement.importClause.namedBindings.elements.map(
|
||||
(binding) => {
|
||||
(binding: Identifier & { name?: { text: string } }) => {
|
||||
if (binding.escapedText) {
|
||||
binding.name = {
|
||||
text: binding.escapedText,
|
||||
text: binding.escapedText as string,
|
||||
};
|
||||
}
|
||||
return binding;
|
||||
@@ -71,7 +75,7 @@ function transformImports(file: SourceFile, ctx: TransformationContext, ngcBuild
|
||||
|
||||
export function importsTransformer(ngcBuild?: boolean) {
|
||||
return (ctx: TransformationContext) => {
|
||||
return (tsSourceFile) => {
|
||||
return (tsSourceFile: SourceFile) => {
|
||||
return transformImports(tsSourceFile, ctx, ngcBuild);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,32 +1,45 @@
|
||||
import { canHaveDecorators, ClassDeclaration, factory, getDecorators as tsGetDecorators, SyntaxKind } from 'typescript';
|
||||
import {
|
||||
canHaveDecorators,
|
||||
ClassDeclaration,
|
||||
ClassElement,
|
||||
ConstructorDeclaration,
|
||||
factory,
|
||||
getDecorators as tsGetDecorators,
|
||||
MethodDeclaration,
|
||||
SyntaxKind,
|
||||
} from 'typescript';
|
||||
|
||||
import { transformMethod } from './methods';
|
||||
import { transformProperty } from './properties';
|
||||
|
||||
export function transformMembers(cls: ClassDeclaration) {
|
||||
export function transformMembers(cls: ClassDeclaration): ClassElement[] {
|
||||
const propertyIndices: number[] = [];
|
||||
|
||||
const members = cls.members.map((member: any, index: number) => {
|
||||
// only process decorated members
|
||||
const members = cls.members.map((member, index) => {
|
||||
const memberDecorators = canHaveDecorators(member) ? tsGetDecorators(member) : undefined;
|
||||
if (!memberDecorators || !memberDecorators.length) return member;
|
||||
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return transformMethod(member);
|
||||
return transformMethod(member as MethodDeclaration) ?? member;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
propertyIndices.push(index);
|
||||
return member;
|
||||
case SyntaxKind.Constructor:
|
||||
return factory.createConstructorDeclaration(undefined, member.parameters, member.body);
|
||||
case SyntaxKind.Constructor: {
|
||||
const ctor = member as ConstructorDeclaration;
|
||||
return factory.createConstructorDeclaration(undefined, ctor.parameters, ctor.body);
|
||||
}
|
||||
default:
|
||||
return member; // in case anything gets here by accident...
|
||||
return member;
|
||||
}
|
||||
});
|
||||
}) as ClassElement[];
|
||||
|
||||
propertyIndices.forEach((i: number) => {
|
||||
const [getter, setter] = transformProperty(members, i) as any;
|
||||
members.push(getter, setter);
|
||||
const result = transformProperty(members, i);
|
||||
if (Array.isArray(result)) {
|
||||
const [getter, setter] = result;
|
||||
members.push(getter, setter);
|
||||
}
|
||||
});
|
||||
|
||||
propertyIndices.reverse().forEach((i) => members.splice(i, 1));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Expression, factory, MethodDeclaration, SyntaxKind } from 'typescript';
|
||||
import { Expression, factory, Identifier, MethodDeclaration, SyntaxKind } from 'typescript';
|
||||
|
||||
import { Logger } from '../../logger';
|
||||
import {
|
||||
@@ -12,9 +12,11 @@ import {
|
||||
export function transformMethod(method: MethodDeclaration) {
|
||||
if (!method) return;
|
||||
|
||||
const decorator = getDecorator(method),
|
||||
decoratorName = getDecoratorName(decorator),
|
||||
decoratorArgs = getDecoratorArgs(decorator);
|
||||
const decorator = getDecorator(method);
|
||||
if (!decorator) return;
|
||||
|
||||
const decoratorName = getDecoratorName(decorator);
|
||||
const decoratorArgs = getDecoratorArgs(decorator);
|
||||
|
||||
try {
|
||||
return factory.createMethodDeclaration(
|
||||
@@ -27,13 +29,17 @@ export function transformMethod(method: MethodDeclaration) {
|
||||
method.type,
|
||||
factory.createBlock([factory.createReturnStatement(getMethodBlock(method, decoratorName, decoratorArgs))])
|
||||
);
|
||||
} catch (e) {
|
||||
Logger.error('Error transforming method: ' + (method.name as any).text);
|
||||
Logger.error(e.message);
|
||||
} catch (e: unknown) {
|
||||
Logger.error('Error transforming method: ' + (method.name as Identifier).text);
|
||||
Logger.error(e instanceof Error ? e.message : String(e));
|
||||
}
|
||||
}
|
||||
|
||||
function getMethodBlock(method: MethodDeclaration, decoratorName: string, decoratorArgs: any): Expression {
|
||||
function getMethodBlock(
|
||||
method: MethodDeclaration,
|
||||
decoratorName: string,
|
||||
decoratorArgs: Record<string, string | number | boolean | string[]>
|
||||
): Expression {
|
||||
const decoratorMethod = getMethodsForDecorator(decoratorName)[0];
|
||||
|
||||
switch (decoratorName) {
|
||||
@@ -46,14 +52,14 @@ function getMethodBlock(method: MethodDeclaration, decoratorName: string, decora
|
||||
SyntaxKind.EqualsEqualsEqualsToken,
|
||||
factory.createTrue()
|
||||
),
|
||||
method.body
|
||||
method.body!
|
||||
),
|
||||
]);
|
||||
|
||||
default:
|
||||
return factory.createCallExpression(factory.createIdentifier(decoratorMethod), undefined, [
|
||||
factory.createThis(),
|
||||
factory.createStringLiteral(decoratorArgs?.methodName || (method.name as any).text),
|
||||
factory.createStringLiteral((decoratorArgs?.methodName as string) || (method.name as Identifier).text),
|
||||
convertValueToLiteral(decoratorArgs),
|
||||
factory.createIdentifier('arguments'),
|
||||
]);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import {
|
||||
canHaveDecorators,
|
||||
canHaveModifiers,
|
||||
ClassDeclaration,
|
||||
Decorator,
|
||||
factory,
|
||||
getDecorators as tsGetDecorators,
|
||||
getModifiers as tsGetModifiers,
|
||||
Identifier,
|
||||
SourceFile,
|
||||
SyntaxKind,
|
||||
TransformationContext,
|
||||
@@ -16,16 +18,15 @@ import { Logger } from '../../logger';
|
||||
import { convertValueToLiteral, getDecorator, getDecoratorArgs, getDecoratorName } from '../helpers';
|
||||
import { transformMembers } from './members';
|
||||
|
||||
function transformClass(cls: any, ngcBuild?: boolean) {
|
||||
Logger.profile('transformClass: ' + cls.name.text);
|
||||
function transformClass(cls: ClassDeclaration, ngcBuild?: boolean) {
|
||||
Logger.profile('transformClass: ' + cls.name!.text);
|
||||
|
||||
const pluginStatics = [];
|
||||
const dec: Decorator = getDecorator(cls);
|
||||
const dec = getDecorator(cls);
|
||||
|
||||
if (dec) {
|
||||
const pluginDecoratorArgs = getDecoratorArgs(dec);
|
||||
|
||||
// add plugin decorator args as static properties of the plugin's class
|
||||
for (const prop in pluginDecoratorArgs) {
|
||||
pluginStatics.push(
|
||||
factory.createPropertyDeclaration(
|
||||
@@ -45,7 +46,7 @@ function transformClass(cls: any, ngcBuild?: boolean) {
|
||||
? clsDecorators.filter((d: Decorator) => getDecoratorName(d) === 'Injectable')
|
||||
: [];
|
||||
|
||||
cls = factory.createClassDeclaration(
|
||||
const result = factory.createClassDeclaration(
|
||||
[...keepDecorators, factory.createToken(SyntaxKind.ExportKeyword)],
|
||||
cls.name,
|
||||
cls.typeParameters,
|
||||
@@ -53,8 +54,8 @@ function transformClass(cls: any, ngcBuild?: boolean) {
|
||||
[...transformMembers(cls), ...pluginStatics]
|
||||
);
|
||||
|
||||
Logger.profile('transformClass: ' + cls.name.text);
|
||||
return cls;
|
||||
Logger.profile('transformClass: ' + (result.name as Identifier).text);
|
||||
return result;
|
||||
}
|
||||
|
||||
function transformClasses(file: SourceFile, ctx: TransformationContext, ngcBuild?: boolean) {
|
||||
@@ -68,7 +69,7 @@ function transformClasses(file: SourceFile, ctx: TransformationContext, ngcBuild
|
||||
) {
|
||||
return node;
|
||||
}
|
||||
return transformClass(node, ngcBuild);
|
||||
return transformClass(node as ClassDeclaration, ngcBuild);
|
||||
},
|
||||
ctx
|
||||
);
|
||||
@@ -76,7 +77,7 @@ function transformClasses(file: SourceFile, ctx: TransformationContext, ngcBuild
|
||||
|
||||
export function pluginClassTransformer(ngcBuild?: boolean): TransformerFactory<SourceFile> {
|
||||
return (ctx: TransformationContext) => {
|
||||
return (tsSourceFile) => {
|
||||
return (tsSourceFile: SourceFile) => {
|
||||
if (tsSourceFile.fileName.indexOf('src/@awesome-cordova-plugins/plugins') > -1) {
|
||||
return transformClasses(tsSourceFile, ctx, ngcBuild);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import { factory, PropertyDeclaration } from 'typescript';
|
||||
import {
|
||||
ClassElement,
|
||||
factory,
|
||||
GetAccessorDeclaration,
|
||||
Identifier,
|
||||
PropertyDeclaration,
|
||||
SetAccessorDeclaration,
|
||||
} from 'typescript';
|
||||
|
||||
import { getDecorator, getDecoratorName } from '../helpers';
|
||||
|
||||
export function transformProperty(members: any[], index: number) {
|
||||
export function transformProperty(
|
||||
members: ClassElement[],
|
||||
index: number
|
||||
): [GetAccessorDeclaration, SetAccessorDeclaration] | PropertyDeclaration {
|
||||
const property = members[index] as PropertyDeclaration,
|
||||
decorator = getDecorator(property),
|
||||
decoratorName = getDecoratorName(decorator);
|
||||
decoratorName = decorator ? getDecoratorName(decorator) : undefined;
|
||||
|
||||
let type: 'cordova' | 'instance';
|
||||
|
||||
@@ -22,6 +32,8 @@ export function transformProperty(members: any[], index: number) {
|
||||
return property;
|
||||
}
|
||||
|
||||
const propertyName = (property.name as Identifier).text;
|
||||
|
||||
const getter = factory.createGetAccessorDeclaration(
|
||||
undefined,
|
||||
property.name,
|
||||
@@ -31,7 +43,7 @@ export function transformProperty(members: any[], index: number) {
|
||||
factory.createReturnStatement(
|
||||
factory.createCallExpression(factory.createIdentifier(type + 'PropertyGet'), undefined, [
|
||||
factory.createThis(),
|
||||
factory.createStringLiteral((property.name as any).text),
|
||||
factory.createStringLiteral(propertyName),
|
||||
])
|
||||
),
|
||||
])
|
||||
@@ -45,7 +57,7 @@ export function transformProperty(members: any[], index: number) {
|
||||
factory.createExpressionStatement(
|
||||
factory.createCallExpression(factory.createIdentifier(type + 'PropertySet'), undefined, [
|
||||
factory.createThis(),
|
||||
factory.createStringLiteral((property.name as any).text),
|
||||
factory.createStringLiteral(propertyName),
|
||||
factory.createIdentifier('value'),
|
||||
])
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user