Browse Source

Add generic parser import method.

Improve generic method, I can work with multiple generic params.
pull/17804/head
Mahmut Gundogdu 3 years ago
parent
commit
efc63f63c0
  1. 129
      npm/ng-packs/packages/schematics/src/tests/parse-generic-type.spec.ts
  2. 35
      npm/ng-packs/packages/schematics/src/utils/model.ts
  3. 31
      npm/ng-packs/packages/schematics/src/utils/tree.ts

129
npm/ng-packs/packages/schematics/src/tests/parse-generic-type.spec.ts

@ -0,0 +1,129 @@
import { parseBaseTypeWithGenericTypes } from '../utils/model';
import { parseGenerics } from '../utils/tree';
import {test} from '@jest/globals';
const cases: Array<[string, string[]]> = [
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
['Volo.Abp.Application.Dtos.AuditedEntityWithUserDto'],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto>',
['Volo.Abp.Application.Dtos.AuditedEntityWithUserDto', 'Volo.Abp.Identity.IdentityUserDto'],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<string,Volo.Abp.Identity.IdentityUserDto>',
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
'string',
'Volo.Abp.Identity.IdentityUserDto'
],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<string,Volo.Abp.Identity.IdentityUserDto<number>>',
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
'string',
'Volo.Abp.Identity.IdentityUserDto',
'number',
],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<string,Volo.Abp.Identity.IdentityUserDto<Volo.Abp.Core.Dummy<System.String>>>',
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
'string',
'Volo.Abp.Identity.IdentityUserDto',
'Volo.Abp.Core.Dummy',
'System.String',
],
],
[
'AuditedEntityWithUserDto',
['AuditedEntityWithUserDto'],
],
];
test.each(cases)('should parse %s', (inputStr, expected) => {
const parsed = parseBaseTypeWithGenericTypes(inputStr);
expect(parsed).toEqual(expected);
})
describe('parseGenerics', () => {
it('should work with simple type', function() {
const node = parseGenerics('System.String');
expect(node.data).toEqual('System.String');
expect(node.index).toBe(0);
expect(node.parent).toBe(null);
});
it('should work with simple Array type', function() {
const node = parseGenerics('System.String[]');
expect(node.data).toEqual('System.String[]');
expect(node.index).toBe(0);
expect(node.parent).toBe(null);
});
it('should work with simple', function() {
const node = parseGenerics('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.index).toBe(0);
expect(node.parent).toBe(null);
});
it('should work with `Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto>`', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(1);
const child = node.children[0];
expect(node.children[0].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(child.parent).toBe(node);
});
it('should work with `Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto>`', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(2);
expect(node.children[0].data).toEqual('System.string');
expect(node.children[0].index).toBe(0)
expect(node.children[1].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(node.children[1].index).toBe(1);
});
it('should Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto<System.Int>>', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto<System.Int>>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(2);
expect(node.children[0].data).toEqual('System.string');
expect((node.children[0]).parent).toBe(node);
expect(node.children[1].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(node.children[1].children.length).toBe(1);
expect(node.children[1].children[0].data).toEqual('System.Int');
expect(node.children[1].children[0].parent).toBe(node.children[1])
expect(node.children[1].children[0].index).toBe(0)
});
it('should Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto<System.Int>,System.string>', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto<System.Int>,System.string>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(2);
expect(node.children[0].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(node.children[0].children.length).toBe(1);
expect(node.children[0].children[0].data).toEqual('System.Int');
expect(node.children[1].data).toEqual('System.string');
});
});

35
npm/ng-packs/packages/schematics/src/utils/model.ts

@ -9,7 +9,7 @@ import {
import { parseNamespace } from './namespace';
import { relativePathToModel } from './path';
import { camel } from './text';
import { parseGenerics } from './tree';
import { parseGenerics, TypeNode } from './tree';
import {
createTypeParser,
createTypeSimplifier,
@ -71,12 +71,16 @@ export function createImportRefsToModelReducer(params: ModelGeneratorParams) {
model.interfaces.forEach(_interface => {
const { baseType } = types[_interface.ref];
if (baseType && parseNamespace(solution, baseType) !== model.namespace)
toBeImported.push({
type: baseType.split('<')[0],
isEnum: false,
});
if (baseType && parseNamespace(solution, baseType) !== model.namespace){
const baseTypeWithGenericParams = parseBaseTypeWithGenericTypes(baseType);
baseTypeWithGenericParams.forEach(t => {
toBeImported.push({
type: t,
isEnum: false,
});
})
}
[..._interface.properties, ..._interface.generics].forEach(prop => {
prop.refs.forEach(ref => {
const propType = types[ref];
@ -172,7 +176,20 @@ export function createRefToImportReducerCreator(params: ModelGeneratorParams) {
}
function isOptionalProperty(prop: PropertyDef) {
return (
prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && prop.isRequired === false)
);
return (prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && !prop.isRequired));
}
export function parseBaseTypeWithGenericTypes(type: string): string[] {
const parsedTypeNode = parseGenerics(type);
const nodeToText = (node: TypeNode,acc:string[] = []): string[] => {
acc.push(node.data);
if(node.children && node.children.length > 0){
node.children.forEach(child => {
nodeToText(child,acc);
})
}
return acc;
}
return nodeToText(parsedTypeNode);
}

31
npm/ng-packs/packages/schematics/src/utils/tree.ts

@ -39,7 +39,7 @@ export class TypeNode {
}
}
export function parseGenerics(type: string, mapperFn?: TypeNodeMapperFn) {
export function parseGenericsOld(type: string, mapperFn?: TypeNodeMapperFn) {
const [rootType, ...types] = type.split('<');
const root = new TypeNode(rootType, null, mapperFn);
@ -68,4 +68,33 @@ export function parseGenerics(type: string, mapperFn?: TypeNodeMapperFn) {
return root;
}
export function parseGenerics(type: string, mapperFn?: TypeNodeMapperFn, parent?: TypeNode | null): TypeNode {
const regex = /(?<MainType>[\w.]+)<(?<GenericType>.*)>/;
const match = type.match(regex);
if (!match) {
return new TypeNode(type, null, mapperFn);
}
const mainType = match.groups?.MainType || '';
const genericType = match.groups?.GenericType || '';
const root = new TypeNode(mainType, parent ?? null, mapperFn);
if (genericType.includes(',')) {
const genericTypes = genericType.split(',');
genericTypes.forEach((genericType, index) => {
const child = parseGenerics(genericType, mapperFn, root);
child.index = index;
root.children.push(child);
child.parent = root;
});
} else {
const child = parseGenerics(genericType, mapperFn, root);
child.index = root.children.length;
root.children.push(child);
child.parent = root;
}
return root;
}
export type TypeNodeMapperFn = (node: TypeNode) => string;

Loading…
Cancel
Save