Add ability to filter out duplicate and generic parameter types
This should make it easier to generate interfaces and use the type references.
This commit is contained in:
parent
3937778e06
commit
aa78b12e54
@ -1,6 +1,14 @@
|
|||||||
import * as ts from 'typescript'
|
import * as ts from 'typescript'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
|
||||||
|
function isObjectType(type: ts.Type): type is ts.ObjectType {
|
||||||
|
return !!(type.flags & ts.TypeFlags.Object)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTypeReference(type: ts.ObjectType): type is ts.TypeReference {
|
||||||
|
return !!(type.objectFlags & ts.ObjectFlags.Reference)
|
||||||
|
}
|
||||||
|
|
||||||
export function typecheck() {
|
export function typecheck() {
|
||||||
interface DocEntry {
|
interface DocEntry {
|
||||||
name?: string
|
name?: string
|
||||||
@ -32,22 +40,51 @@ export function typecheck() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
function typeToString(type: ts.Type): string {
|
||||||
|
return checker.typeToString(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterGlobalTypes(type: ts.Type): boolean {
|
||||||
|
const symbol = type.getSymbol()
|
||||||
|
if (symbol && !((symbol as any).parent)) {
|
||||||
|
// e.g. Array symbol has no parent
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (type.isUnionOrIntersection()) {
|
||||||
|
// union type params should have already been extracted
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapGenericTypes(type: ts.Type): ts.Type {
|
||||||
|
if (isObjectType(type) && isTypeReference(type)) {
|
||||||
|
return type.target
|
||||||
|
}
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterDuplicates(type: ts.Type, i: number, arr: ts.Type[]) {
|
||||||
|
// TODO improve performance of this method
|
||||||
|
return i === arr.indexOf(type)
|
||||||
|
}
|
||||||
|
|
||||||
function getAllTypeParameters(type: ts.Type): ts.Type[] {
|
function getAllTypeParameters(type: ts.Type): ts.Type[] {
|
||||||
console.log('TTT', checker.typeToString(type),
|
// console.log('TTT', checker.typeToString(type),
|
||||||
{
|
// {
|
||||||
isObject: !!(type.flags & ts.TypeFlags.Object),
|
// isObject: !!(type.flags & ts.TypeFlags.Object),
|
||||||
isTuple: (type as any).objectFlags & ts.ObjectFlags.Tuple,
|
// isTuple: (type as any).objectFlags & ts.ObjectFlags.Tuple,
|
||||||
objectFlags: (type as any).objectFlags,
|
// typeFlags: type.flags,
|
||||||
},
|
// objectFlags: (type as any).objectFlags,
|
||||||
)
|
// },
|
||||||
if (type.flags & ts.TypeFlags.Object) {
|
// )
|
||||||
const objectType = type as ts.ObjectType
|
if (isObjectType(type)) {
|
||||||
const objectFlags = objectType.objectFlags
|
if (isTypeReference(type)) {
|
||||||
if (objectFlags & ts.ObjectFlags.Reference) {
|
const types: ts.Type[] = [type]
|
||||||
const types = [type]
|
|
||||||
const typeRef = type as ts.TypeReference
|
if (type.typeArguments) {
|
||||||
if (typeRef.typeArguments) {
|
type.typeArguments.forEach(t => {
|
||||||
typeRef.typeArguments.forEach(t => {
|
|
||||||
const ta = getAllTypeParameters(t)
|
const ta = getAllTypeParameters(t)
|
||||||
types.push(...ta)
|
types.push(...ta)
|
||||||
})
|
})
|
||||||
@ -104,9 +141,11 @@ export function typecheck() {
|
|||||||
if (ts.isClassDeclaration(node) && node.name) {
|
if (ts.isClassDeclaration(node) && node.name) {
|
||||||
// This is a top level class, get its symbol
|
// This is a top level class, get its symbol
|
||||||
const symbol = checker.getSymbolAtLocation(node.name)
|
const symbol = checker.getSymbolAtLocation(node.name)
|
||||||
|
|
||||||
|
const typeParameters: ts.Type[] = []
|
||||||
if (symbol) {
|
if (symbol) {
|
||||||
console.log('===')
|
console.log('===')
|
||||||
console.log('text', node.getText(node.getSourceFile()))
|
// console.log('text', node.getText(node.getSourceFile()))
|
||||||
console.log('class', symbol.getName())
|
console.log('class', symbol.getName())
|
||||||
const type = checker.getDeclaredTypeOfSymbol(symbol)
|
const type = checker.getDeclaredTypeOfSymbol(symbol)
|
||||||
|
|
||||||
@ -115,13 +154,17 @@ export function typecheck() {
|
|||||||
console.log(' tp.symbol.name', tp.symbol.name)
|
console.log(' tp.symbol.name', tp.symbol.name)
|
||||||
const constraint = tp.getConstraint()
|
const constraint = tp.getConstraint()
|
||||||
if (constraint) {
|
if (constraint) {
|
||||||
|
// TODO call getAllTypeParameters here...
|
||||||
console.log(' tp.constraint',
|
console.log(' tp.constraint',
|
||||||
checker.typeToString(constraint))
|
checker.typeToString(constraint))
|
||||||
}
|
}
|
||||||
const def = tp.getDefault()
|
const def = tp.getDefault()
|
||||||
if (def) {
|
if (def) {
|
||||||
|
// TODO call getAllTypeParameters here...
|
||||||
console.log(' tp.default', checker.typeToString(def))
|
console.log(' tp.default', checker.typeToString(def))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeParameters.push(tp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,31 +186,19 @@ export function typecheck() {
|
|||||||
const propType = checker
|
const propType = checker
|
||||||
.getTypeOfSymbolAtLocation(p, p.valueDeclaration)
|
.getTypeOfSymbolAtLocation(p, p.valueDeclaration)
|
||||||
|
|
||||||
const s = propType.getSymbol()
|
const typeParams = getAllTypeParameters(propType)
|
||||||
if (s) {
|
|
||||||
// if (ts,
|
|
||||||
// console.log(' ', p.getName(), checker.getFullyQualifiedName(s))
|
|
||||||
// s.value
|
|
||||||
// checker.
|
|
||||||
// const d = s.getDeclarations()
|
|
||||||
// if (d) {
|
|
||||||
// d.forEach(dec => {
|
|
||||||
// console.log(' ', dec.getText())
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
p.flags
|
|
||||||
|
|
||||||
console.log('---')
|
|
||||||
return {
|
return {
|
||||||
name: p.getName(),
|
name: p.getName(),
|
||||||
type: checker.typeToString(propType),
|
type: checker.typeToString(propType),
|
||||||
questionToken,
|
questionToken,
|
||||||
typeParams: getAllTypeParameters(propType).map(
|
typeParams: typeParams.map(typeToString),
|
||||||
t => checker.typeToString(t)),
|
filteredTypeParams: typeParams
|
||||||
// classOrIface: propType.isClassOrInterface(),
|
.filter(filterGlobalTypes)
|
||||||
// union: propType.isUnion(),
|
// filter class type parameters
|
||||||
|
.filter(t => typeParameters.every(tp => tp !== t))
|
||||||
|
.map(mapGenericTypes)
|
||||||
|
.filter(filterDuplicates)
|
||||||
|
.map(typeToString),
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
// output.push(serializeClass(symbol))
|
// output.push(serializeClass(symbol))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user