mirror of https://github.com/abpframework/abp.git
2 changed files with 101 additions and 0 deletions
@ -0,0 +1,100 @@ |
|||||
|
import { Generic } from '../models'; |
||||
|
|
||||
|
export class GenericsCollector { |
||||
|
private _generics: Generic[] = []; |
||||
|
get generics() { |
||||
|
return this._generics; |
||||
|
} |
||||
|
|
||||
|
apply = (value: string, index: number) => { |
||||
|
const generic = this.get(index); |
||||
|
if (generic) { |
||||
|
if (!generic.type) generic.setType(value); |
||||
|
return value + generic.default; |
||||
|
} |
||||
|
|
||||
|
return value; |
||||
|
}; |
||||
|
|
||||
|
constructor(private getTypeIdentifier = (type: string) => type) {} |
||||
|
|
||||
|
private createGeneric(type: string, ref: string, defaultValue: string) { |
||||
|
const _default = this.getTypeIdentifier(defaultValue); |
||||
|
const refs = [generateRefWithPlaceholders(ref)]; |
||||
|
const generic = new Generic({ type, default: _default, refs }); |
||||
|
return generic; |
||||
|
} |
||||
|
|
||||
|
private register(index: number, generic: Generic) { |
||||
|
const existing = this.get(index); |
||||
|
if (existing) { |
||||
|
existing.setDefault(generic.default); |
||||
|
existing.setType(generic.type); |
||||
|
} else this.set(index, generic); |
||||
|
} |
||||
|
|
||||
|
collect(generics: string[], genericArguments: string[]) { |
||||
|
generics.forEach((ref, i) => { |
||||
|
const generic = this.createGeneric( |
||||
|
genericArguments[i], |
||||
|
ref, |
||||
|
genericArguments.includes(ref) ? '' : ref, |
||||
|
); |
||||
|
this.register(i, generic); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
get(index: number) { |
||||
|
return this.generics[index]; |
||||
|
} |
||||
|
|
||||
|
set(index: number, value: Generic) { |
||||
|
this.generics[index] = value; |
||||
|
} |
||||
|
|
||||
|
reset() { |
||||
|
this._generics = []; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function generateRefWithPlaceholders(sourceType: string) { |
||||
|
let { identifier, generics } = extractGenerics(sourceType); |
||||
|
|
||||
|
identifier = identifier; |
||||
|
generics = generics.map((_, i) => `T${i}`); |
||||
|
|
||||
|
return generics.length ? `${identifier}<${generics}>` : identifier; |
||||
|
} |
||||
|
|
||||
|
export function extractSimpleGenerics(sourceType: string) { |
||||
|
const { identifier, generics } = extractGenerics(sourceType); |
||||
|
|
||||
|
return { |
||||
|
identifier: getLastSegment(identifier), |
||||
|
generics: generics.map(getLastSegment), |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export function extractGenerics(sourceType: string) { |
||||
|
const regex = /(?<identifier>[^<]+)(<(?<generics>.+)>)?/g; |
||||
|
const { identifier = '', generics = '' } = regex.exec(sourceType)?.groups ?? {}; |
||||
|
|
||||
|
return { |
||||
|
identifier, |
||||
|
generics: generics.split(/,\s*/).filter(Boolean), |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
function getLastSegment(str: string) { |
||||
|
return str.split('.').pop()!; |
||||
|
} |
||||
|
|
||||
|
export function replacePlaceholdersWithGenerics( |
||||
|
type: string, |
||||
|
generics: string[], |
||||
|
genericsCollector: GenericsCollector, |
||||
|
) { |
||||
|
return generics |
||||
|
.map(genericsCollector.apply) |
||||
|
.reduce((acc, v, i) => acc.replace(new RegExp(`([<, ])T${i}([,>])`, 'g'), `$1${v}$2`), type); |
||||
|
} |
||||
Loading…
Reference in new issue