(program: ts.Program, input: ts.ClassDeclaration)
| 29 | type Writeable<T> = { -readonly [P in keyof T]: T[P] }; |
| 30 | |
| 31 | export function buildTypeSchema(program: ts.Program, input: ts.ClassDeclaration) { |
| 32 | const schema: TypeSchema = { |
| 33 | properties: [], |
| 34 | isStrict: !!ts.getJSDocTags(input).find(t => t.tagName.text === 'json_strict'), |
| 35 | hasToJsonExtension: false, |
| 36 | hasSetPropertyExtension: false |
| 37 | }; |
| 38 | |
| 39 | const handleMember = ( |
| 40 | member: ts.ClassDeclaration['members'][0], |
| 41 | typeArgumentMapping: Map<string, ts.Type> | undefined |
| 42 | ) => { |
| 43 | if (ts.isPropertyDeclaration(member)) { |
| 44 | const propertyDeclaration = member as ts.PropertyDeclaration; |
| 45 | if ( |
| 46 | !propertyDeclaration.modifiers!.find( |
| 47 | m => m.kind === ts.SyntaxKind.StaticKeyword || m.kind === ts.SyntaxKind.PrivateKeyword |
| 48 | ) |
| 49 | ) { |
| 50 | const jsonNames = [(member.name as ts.Identifier).text.toLowerCase()]; |
| 51 | const jsDoc = ts.getJSDocTags(member); |
| 52 | |
| 53 | if (jsDoc.find(t => t.tagName.text === 'json_on_parent')) { |
| 54 | jsonNames.push(''); |
| 55 | } |
| 56 | |
| 57 | if (!jsDoc.find(t => t.tagName.text === 'json_ignore')) { |
| 58 | const asRaw = !!jsDoc.find(t => t.tagName.text === 'json_raw'); |
| 59 | const isReadonly = !!jsDoc.find(t => t.tagName.text === 'json_read_only'); |
| 60 | schema.properties.push({ |
| 61 | jsonNames: jsonNames, |
| 62 | asRaw, |
| 63 | partialNames: !!jsDoc.find(t => t.tagName.text === 'json_partial_names'), |
| 64 | target: jsDoc.find(t => t.tagName.text === 'target')?.comment as string, |
| 65 | isJsonReadOnly: isReadonly, |
| 66 | isReadOnly: propertyDeclaration.modifiers!.some(m => m.kind == ts.SyntaxKind.ReadonlyKeyword), |
| 67 | name: (member.name as ts.Identifier).text, |
| 68 | jsDocTags: jsDoc, |
| 69 | type: getTypeWithNullableInfo( |
| 70 | program, |
| 71 | member.type ?? program.getTypeChecker().getTypeAtLocation(member.name), |
| 72 | asRaw || isReadonly, |
| 73 | !!member.questionToken, |
| 74 | typeArgumentMapping |
| 75 | ) |
| 76 | }); |
| 77 | } |
| 78 | } |
| 79 | } else if (ts.isMethodDeclaration(member)) { |
| 80 | switch ((member.name as ts.Identifier).text) { |
| 81 | case 'toJson': |
| 82 | schema.hasToJsonExtension = true; |
| 83 | break; |
| 84 | case 'setProperty': |
| 85 | schema.hasSetPropertyExtension = true; |
| 86 | break; |
| 87 | } |
| 88 | } |
no test coverage detected