-
Notifications
You must be signed in to change notification settings - Fork 0
/
TypeScriptInterfaceToModelHarvester.ts
72 lines (68 loc) · 2.83 KB
/
TypeScriptInterfaceToModelHarvester.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import ts, { InterfaceDeclaration, SyntaxKind } from 'typescript'
import { Artifact } from '../../system/Artifact'
import { ComponentOrigin } from '../../system/ComponentOrigin'
import { Permanence } from '../../system/Permanence'
import { System } from '../../system/System'
import { SystemComponent } from '../../system/SystemComponent'
import { SystemComponentArtifact } from '../../system/SystemComponentArtifact'
import { SystemComponentType } from '../../system/SystemComponentType'
import { Class, InformationModel, Interface } from '../information-architecture'
import { AbstractTypeScriptAstHarvester } from './AbstractTypeScriptAstHarvester'
export class TypeScriptInterfaceToModelHarvester extends AbstractTypeScriptAstHarvester {
constructor(configurationValues?: { [key: string]: any }) {
super('A harvester that infers the data model from typescript classes', {}, configurationValues)
}
// eslint-disable-next-line max-lines-per-function
async harvestFromAst(system: System, ast: ts.SourceFile): Promise<Artifact[]> {
let representedInterface: Interface
const _thisThis = this
const results = [] as Artifact[]
const model = InformationModel.fromSystem(system)
try {
// eslint-disable-next-line @typescript-eslint/naming-convention, max-lines-per-function
ts.forEachChild(ast, function visit(node: ts.Node) {
switch (node.kind) {
case SyntaxKind.InterfaceDeclaration:
const classDeclaration = node as InterfaceDeclaration
const name = classDeclaration.name?.getText(ast) as string
if (name != null && _thisThis.validClass(name)) {
const fullName = SystemComponent.fullConstantCase(model.fullConstantCaseName, name)
const valueClass = system.descendants[fullName] as Class
if (valueClass == null) {
const memberJsDoc = (node as any).jsDoc as any[]
let memberDocumentationText = ''
if (memberJsDoc != null) {
memberJsDoc.forEach((jsDocItem) => {
memberDocumentationText += jsDocItem.comment as string
})
}
representedInterface = new Interface(
model.fullConstantCaseName,
name,
memberDocumentationText,
SystemComponentType.informationModel
)
representedInterface.permanence = Permanence.persistent
representedInterface.informational = true
representedInterface.functional = false
representedInterface.origin = ComponentOrigin.harvested
representedInterface.primitive = false
model.addChild(representedInterface)
results.push(new SystemComponentArtifact(representedInterface))
ts.forEachChild(node, visit)
}
}
break
default:
// ignore
break
}
//console.log(node.kind);
})
return results
} catch (problem) {
this.logger.error(`harvestFromAst(failed) ${problem}`)
throw problem
}
}
}