Skip to content

Commit

Permalink
refactor(transformer): remove star imports
Browse files Browse the repository at this point in the history
  • Loading branch information
jackey8616 committed Apr 5, 2024
1 parent c623951 commit 33f228e
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as ts from 'typescript';
import type { Node } from 'typescript';
import { Tsoa } from '@tsoa/runtime';

import { Transformer } from './transformer';
import { getJSDocTagNames } from '../../utils/jsDocUtils';

export class DateTransformer extends Transformer {
public transform(parentNode?: ts.Node): Tsoa.DateType | Tsoa.DateTimeType {
public transform(parentNode?: Node): Tsoa.DateType | Tsoa.DateTimeType {
if (!parentNode) {
return { dataType: 'datetime' };
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as ts from 'typescript';
import type { Node, EnumDeclaration, EnumMember } from 'typescript';
import { isEnumDeclaration, isEnumMember } from 'typescript';
import { Tsoa } from '@tsoa/runtime';

import { Transformer } from './transformer';
Expand Down Expand Up @@ -32,18 +33,18 @@ export class EnumTransformer extends Transformer {
};
}

public static transformable(declaration: ts.Node): declaration is ts.EnumDeclaration | ts.EnumMember {
return ts.isEnumDeclaration(declaration) || ts.isEnumMember(declaration);
public static transformable(declaration: Node): declaration is EnumDeclaration | EnumMember {
return isEnumDeclaration(declaration) || isEnumMember(declaration);
}

public transform(declaration: ts.EnumDeclaration | ts.EnumMember, enumName: string): Tsoa.RefEnumType {
if (ts.isEnumDeclaration(declaration)) {
public transform(declaration: EnumDeclaration | EnumMember, enumName: string): Tsoa.RefEnumType {
if (isEnumDeclaration(declaration)) {
return this.transformDeclaration(declaration, enumName);
}
return this.transformMember(declaration, enumName);
}

private transformDeclaration(declaration: ts.EnumDeclaration, enumName: string): Tsoa.RefEnumType {
private transformDeclaration(declaration: EnumDeclaration, enumName: string): Tsoa.RefEnumType {
const isNotUndefined = <T>(item: T): item is Exclude<T, undefined> => {
return item === undefined ? false : true;
}
Expand All @@ -60,7 +61,7 @@ export class EnumTransformer extends Transformer {
};
}

private transformMember(declaration: ts.EnumMember, enumName: string): Tsoa.RefEnumType {
private transformMember(declaration: EnumMember, enumName: string): Tsoa.RefEnumType {
return {
dataType: 'refEnum',
refName: enumName,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import * as ts from 'typescript';
import type { TypeNode, Node } from 'typescript';
import { SyntaxKind } from 'typescript';
import { Tsoa, assertNever } from '@tsoa/runtime';

import { Transformer } from './transformer';
import { getJSDocTagNames } from '../../utils/jsDocUtils';

export class PrimitiveTransformer extends Transformer {
public static resolveKindToPrimitive(syntaxKind: ts.SyntaxKind): ResolvesToPrimitive {
public static resolveKindToPrimitive(syntaxKind: SyntaxKind): ResolvesToPrimitive {
switch (syntaxKind) {
case ts.SyntaxKind.NumberKeyword:
case SyntaxKind.NumberKeyword:
return 'number';
case ts.SyntaxKind.StringKeyword:
case SyntaxKind.StringKeyword:
return 'string';
case ts.SyntaxKind.BooleanKeyword:
case SyntaxKind.BooleanKeyword:
return 'boolean';
case ts.SyntaxKind.VoidKeyword:
case SyntaxKind.VoidKeyword:
return 'void';
case ts.SyntaxKind.UndefinedKeyword:
case SyntaxKind.UndefinedKeyword:
return 'undefined';
default:
return undefined;
}
};

public transform(typeNode: ts.TypeNode, parentNode?: ts.Node): Tsoa.PrimitiveType | undefined {
public transform(typeNode: TypeNode, parentNode?: Node): Tsoa.PrimitiveType | undefined {
const resolvedType = PrimitiveTransformer.resolveKindToPrimitive(typeNode.kind);
if (!resolvedType) {
return;
Expand All @@ -45,7 +46,7 @@ export class PrimitiveTransformer extends Transformer {

private transformNumber(
defaultNumberType: NonNullable<"double" | "float" | "integer" | "long" | undefined>,
parentNode?: ts.Node,
parentNode?: Node,
): Tsoa.PrimitiveType {
if (!parentNode) {
return { dataType: defaultNumberType };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
import * as ts from 'typescript';
import type {
Token,
Identifier,
InterfaceDeclaration,
ClassDeclaration,
PropertyDeclaration,
ParameterDeclaration,
ConstructorDeclaration,
TypeElement,
ClassElement,
PropertySignature,
} from 'typescript';
import {
NodeFlags,
NodeBuilderFlags,
SyntaxKind,
isInterfaceDeclaration,
isPropertyDeclaration,
isConstructorDeclaration,
isPropertySignature,
} from 'typescript';
import { Tsoa } from '@tsoa/runtime';

import { Transformer } from './transformer';
Expand All @@ -10,31 +30,31 @@ import { isExistJSDocTag } from '../../utils/jsDocUtils';
import { isDecorator } from '../../utils/decoratorUtils';
import { throwUnless } from '../../utils/flowUtils';

type OverrideToken = ts.Token<ts.SyntaxKind.QuestionToken> | ts.Token<ts.SyntaxKind.PlusToken> | ts.Token<ts.SyntaxKind.MinusToken> | undefined;
type OverrideToken = Token<SyntaxKind.QuestionToken> | Token<SyntaxKind.PlusToken> | Token<SyntaxKind.MinusToken> | undefined;

export class PropertyTransformer extends Transformer {
public transform(node: ts.InterfaceDeclaration | ts.ClassDeclaration, overrideToken?: OverrideToken): Tsoa.Property[] {
const isIgnored = (e: ts.TypeElement | ts.ClassElement) => {
public transform(node: InterfaceDeclaration | ClassDeclaration, overrideToken?: OverrideToken): Tsoa.Property[] {
const isIgnored = (e: TypeElement | ClassElement) => {
let ignore = isExistJSDocTag(e, tag => tag.tagName.text === 'ignore');
ignore = ignore || (e.flags & ts.NodeFlags.ThisNodeHasError) > 0;
ignore = ignore || (e.flags & NodeFlags.ThisNodeHasError) > 0;
return ignore;
};

// Interface model
if (ts.isInterfaceDeclaration(node)) {
if (isInterfaceDeclaration(node)) {
return node.members
.filter((member): member is ts.PropertySignature => !isIgnored(member) && ts.isPropertySignature(member))
.map((member: ts.PropertySignature) => this.propertyFromSignature(member, overrideToken));
.filter((member): member is PropertySignature => !isIgnored(member) && isPropertySignature(member))
.map((member: PropertySignature) => this.propertyFromSignature(member, overrideToken));
}

const properties: Array<ts.PropertyDeclaration | ts.ParameterDeclaration> = [];
const properties: Array<PropertyDeclaration | ParameterDeclaration> = [];
for (const member of node.members) {
if (!isIgnored(member) && ts.isPropertyDeclaration(member) && !this.hasStaticModifier(member) && this.hasPublicModifier(member)) {
if (!isIgnored(member) && isPropertyDeclaration(member) && !this.hasStaticModifier(member) && this.hasPublicModifier(member)) {
properties.push(member);
}
}

const classConstructor = node.members.find(member => ts.isConstructorDeclaration(member)) as ts.ConstructorDeclaration;
const classConstructor = node.members.find(member => isConstructorDeclaration(member)) as ConstructorDeclaration;

if (classConstructor && classConstructor.parameters) {
const constructorProperties = classConstructor.parameters.filter(parameter => this.isAccessibleParameter(parameter));
Expand All @@ -45,18 +65,18 @@ export class PropertyTransformer extends Transformer {
return properties.map(property => this.propertyFromDeclaration(property, overrideToken));
}

private propertyFromSignature(propertySignature: ts.PropertySignature, overrideToken?: OverrideToken): Tsoa.Property {
const identifier = propertySignature.name as ts.Identifier;
private propertyFromSignature(propertySignature: PropertySignature, overrideToken?: OverrideToken): Tsoa.Property {
const identifier = propertySignature.name as Identifier;

throwUnless(
propertySignature.type,
new GenerateMetadataError(`No valid type found for property declaration.`),
);

let required = !propertySignature.questionToken;
if (overrideToken && overrideToken.kind === ts.SyntaxKind.MinusToken) {
if (overrideToken && overrideToken.kind === SyntaxKind.MinusToken) {
required = true;
} else if (overrideToken && overrideToken.kind === ts.SyntaxKind.QuestionToken) {
} else if (overrideToken && overrideToken.kind === SyntaxKind.QuestionToken) {
required = false;
}

Expand All @@ -77,23 +97,23 @@ export class PropertyTransformer extends Transformer {
return property;
}

private propertyFromDeclaration(propertyDeclaration: ts.PropertyDeclaration | ts.ParameterDeclaration, overrideToken?: OverrideToken): Tsoa.Property {
const identifier = propertyDeclaration.name as ts.Identifier;
private propertyFromDeclaration(propertyDeclaration: PropertyDeclaration | ParameterDeclaration, overrideToken?: OverrideToken): Tsoa.Property {
const identifier = propertyDeclaration.name as Identifier;
let typeNode = propertyDeclaration.type;

const tsType = this.resolver.current.typeChecker.getTypeAtLocation(propertyDeclaration);

if (!typeNode) {
// Type is from initializer
typeNode = this.resolver.current.typeChecker.typeToTypeNode(tsType, undefined, ts.NodeBuilderFlags.NoTruncation)!;
typeNode = this.resolver.current.typeChecker.typeToTypeNode(tsType, undefined, NodeBuilderFlags.NoTruncation)!;
}

const type = new TypeResolver(typeNode, this.resolver.current, propertyDeclaration, this.resolver.context, tsType).resolve();

let required = !propertyDeclaration.questionToken && !propertyDeclaration.initializer;
if (overrideToken && overrideToken.kind === ts.SyntaxKind.MinusToken) {
if (overrideToken && overrideToken.kind === SyntaxKind.MinusToken) {
required = true;
} else if (overrideToken && overrideToken.kind === ts.SyntaxKind.QuestionToken) {
} else if (overrideToken && overrideToken.kind === SyntaxKind.QuestionToken) {
required = false;
}
let def = getInitializerValue(propertyDeclaration.initializer, this.resolver.current.typeChecker);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as ts from 'typescript';
import type { TypeAliasDeclaration, Type } from 'typescript';
import { Tsoa } from '@tsoa/runtime';

import { Transformer } from './transformer';
Expand Down Expand Up @@ -66,7 +66,7 @@ export class ReferenceTransformer extends Transformer {
return result;
}

public transform(declaration: ts.TypeAliasDeclaration, refTypeName: string, referencer?: ts.Type): Tsoa.ReferenceType {
public transform(declaration: TypeAliasDeclaration, refTypeName: string, referencer?: Type): Tsoa.ReferenceType {
const example = this.resolver.getNodeExample(declaration);

const referenceType: Tsoa.ReferenceType = {
Expand Down
21 changes: 11 additions & 10 deletions packages/cli/src/metadataGeneration/transformer/transformer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as ts from 'typescript';
import type { HasModifiers } from 'typescript';
import { SyntaxKind, getModifiers } from 'typescript';

import { TypeResolver } from '../typeResolver';

Expand All @@ -10,40 +11,40 @@ export abstract class Transformer {
protected readonly resolver: TypeResolver,
) {}

protected hasPublicModifier(node: ts.HasModifiers): boolean {
protected hasPublicModifier(node: HasModifiers): boolean {
return (
!node.modifiers ||
node.modifiers.every(modifier => {
return modifier.kind !== ts.SyntaxKind.ProtectedKeyword && modifier.kind !== ts.SyntaxKind.PrivateKeyword;
return modifier.kind !== SyntaxKind.ProtectedKeyword && modifier.kind !== SyntaxKind.PrivateKeyword;
})
);
}

protected hasStaticModifier(node: ts.HasModifiers): boolean | undefined {
protected hasStaticModifier(node: HasModifiers): boolean | undefined {
return (
node.modifiers &&
node.modifiers.some(modifier => {
return modifier.kind === ts.SyntaxKind.StaticKeyword;
return modifier.kind === SyntaxKind.StaticKeyword;
})
);
}

protected isAccessibleParameter(node: ts.HasModifiers): boolean {
const modifiers = ts.getModifiers(node);
protected isAccessibleParameter(node: HasModifiers): boolean {
const modifiers = getModifiers(node);

if (modifiers == null || modifiers.length === 0) {
return false;
}

// public || public readonly
if (modifiers.some(modifier => modifier.kind === ts.SyntaxKind.PublicKeyword)) {
if (modifiers.some(modifier => modifier.kind === SyntaxKind.PublicKeyword)) {
return true;
}

// readonly, not private readonly, not public readonly
const isReadonly = modifiers.some(modifier => modifier.kind === ts.SyntaxKind.ReadonlyKeyword);
const isReadonly = modifiers.some(modifier => modifier.kind === SyntaxKind.ReadonlyKeyword);
const isProtectedOrPrivate = modifiers.some(modifier => {
return modifier.kind === ts.SyntaxKind.ProtectedKeyword || modifier.kind === ts.SyntaxKind.PrivateKeyword;
return modifier.kind === SyntaxKind.ProtectedKeyword || modifier.kind === SyntaxKind.PrivateKeyword;
});
return isReadonly && !isProtectedOrPrivate;
}
Expand Down

0 comments on commit 33f228e

Please sign in to comment.