feat: modernize core-tools

This commit is contained in:
Wieland Schöbl
2021-08-25 09:47:36 +00:00
parent 106dd26f89
commit fe59204b42
106 changed files with 4131 additions and 6216 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 StApps
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -15,12 +15,13 @@
import {Logger} from '@openstapps/logger';
import {createWriteStream} from 'fs';
import * as request from 'got';
import {getFullTypeName} from '../common';
import {LightweightClassDefinition} from './model/lightweight-class-definition';
import {LightweightDefinition} from './model/lightweight-definition';
import {LightweightEnumDefinition} from './model/lightweight-enum-definition';
import {LightweightProperty} from './model/lightweight-property';
import {LightweightType} from './model/lightweight-type';
import {forEach, map, isEmpty} from 'lodash';
import {expandTypeValue, isLightweightClass, isUnionOrIntersectionType} from '../easy-ast/ast-util';
import {LightweightAliasDefinition} from '../easy-ast/types/lightweight-alias-definition';
import {LightweightClassDefinition} from '../easy-ast/types/lightweight-class-definition';
import {LightweightDefinition} from '../easy-ast/types/lightweight-definition';
import {LightweightProperty} from '../easy-ast/types/lightweight-property';
import {LightweightType} from '../easy-ast/types/lightweight-type';
import {UMLConfig} from './uml-config';
/**
@@ -28,7 +29,7 @@ import {UMLConfig} from './uml-config';
* to valid PlantUML Code, which will then be encoded, converted by the plantuml server
* and saved as a .svg file in directory, in which this method was called
*
* @param definitions all type definitons of the project
* @param definitions all type definitions of the project
* @param config contains information on how the PlantUML should be generated
* @param plantUmlBaseURL Hostname of the PlantUML-Server
*/
@@ -37,49 +38,29 @@ export async function createDiagram(
config: UMLConfig,
plantUmlBaseURL: string,
): Promise<string> {
// when non definitions were specified use all
if (config.definitions.length === 0) {
config.definitions = [];
definitions.forEach((definition) => {
config.definitions.push(definition.name);
});
}
config.definitions = map(definitions, 'name');
// when providing definitions and either showing associations or inheritance the
// inherited definitions will be added automatically
if (config.showInheritance) {
const inheritedDefinitions = gatherTypeAssociations(
// TODO: showInheritance
/*const inheritedDefinitions = gatherTypeAssociations(
definitions,
config.definitions,
);
config.definitions = config.definitions.concat(inheritedDefinitions);
);*/
// config.definitions = config.definitions.concat(inheritedDefinitions);
}
let modelPlantUMLCode = '';
// creates a UML definition for every specified definition name
// however if no definitions were provided all definitions will be transformed
for (const definition of definitions) {
if (
config.definitions.length > 0 &&
!config.definitions.includes(definition.name)
) {
// current definition not specified
continue;
}
// either the definitions are empty or the definition was specified, proceed
let definitionPlantUMLCode = '';
if (definition instanceof LightweightClassDefinition) {
definitionPlantUMLCode = createPlantUMLCodeForClass(config, definition);
} else if (definition instanceof LightweightEnumDefinition) {
definitionPlantUMLCode = createPlantUMLCodeForEnum(config, definition);
} else {
continue;
}
modelPlantUMLCode += definitionPlantUMLCode;
}
const modelPlantUMLCode = map(
definitions.filter(it => !config.definitions.includes(it.name)),
definition =>
isLightweightClass(definition)
? createPlantUMLCodeForClass(config, definition)
: createPlantUMLCodeForEnum(config, definition),
).join('');
return createDiagramFromString(modelPlantUMLCode, plantUmlBaseURL, config.outputFileName);
}
@@ -97,6 +78,7 @@ export async function createDiagramFromString(
plantUmlBaseURL: string,
outputFile = `Diagram-${new Date().toISOString()}`,
) {
// eslint-disable-next-line @typescript-eslint/no-var-requires,unicorn/prefer-module
const plantumlEncoder = require('plantuml-encoder');
const plantUMLCode = plantumlEncoder.encode(`@startuml\n${modelPlantUMLCode}\n@enduml`);
const url = `${plantUmlBaseURL}/svg/${plantUMLCode}`;
@@ -108,17 +90,18 @@ export async function createDiagramFromString(
await Logger.error(`Plantuml Server responded with an error.\n${response.statusMessage}`);
throw new Error('Response not okay');
}
} catch (e) {
Logger.log(`Please try using the public plantuml server:\nhttp://www.plantuml.com/plantuml/svg/${plantUMLCode}`);
throw e;
} catch (error) {
Logger.log(
`Please try using the public plantuml server:\nhttp://www.plantuml.com/plantuml/svg/${plantUMLCode}`,
);
throw error;
}
// attach file extension
const fileName = `${outputFile}.svg`;
try {
createWriteStream(fileName)
.write(response.body);
createWriteStream(fileName).write(response.body);
Logger.log(`Writen data to file: ${fileName}`);
} catch (e) {
} catch {
throw new Error('Could not write file. Are you missing permissions?');
}
@@ -126,12 +109,13 @@ export async function createDiagramFromString(
}
/**
* Recursivly iterates over all types, to find implemented generic types and parents
* Recursively iterates over all types, to find implemented generic types and parents
*
* @param definitions all type definitons of the project
* @param definitions all type definitions of the project
* @param abstractionNames currently known string values of inherited classes
*/
function gatherTypeAssociations(
/*function gatherTypeAssociations(
definitions: LightweightDefinition[],
abstractionNames: string[],
): string[] {
@@ -140,7 +124,7 @@ function gatherTypeAssociations(
const declaration = definitions.find(
(definition) => definition.name === name,
);
if (declaration instanceof LightweightClassDefinition) {
if (isLightweightClass(declaration)) {
const currentAbstractions: string[] = declaration.extendedDefinitions.concat(
declaration.implementedDefinitions,
);
@@ -153,7 +137,7 @@ function gatherTypeAssociations(
}
return abstractions;
}
}*/
/**
* Collects all reference information of this type.
@@ -164,25 +148,22 @@ function gatherTypeAssociations(
*/
function getReferenceTypes(type: LightweightType): string[] {
const types: string[] = [];
if (type.isReference) {
types.push(type.name);
if (typeof type.referenceName !== 'undefined') {
types.push(type.referenceName);
}
if (type.isTyped && type.genericsTypes.length > 0) {
for (const specificType of type.genericsTypes) {
forEach(type.genericsTypes, specificType => {
for (const value of getReferenceTypes(specificType)) {
types.push(value);
}
});
if ((isUnionOrIntersectionType(type) && isEmpty(type.specificationTypes)) || type.isArray) {
forEach(type.specificationTypes, specificType => {
for (const value of getReferenceTypes(specificType)) {
types.push(value);
}
}
}
if (
(type.isUnion && type.specificationTypes.length > 0) ||
(type.isArray && type.specificationTypes.length > 0)
) {
for (const specificType of type.specificationTypes) {
for (const value of getReferenceTypes(specificType)) {
types.push(value);
}
}
});
}
return types;
@@ -194,57 +175,54 @@ function getReferenceTypes(type: LightweightType): string[] {
* @param config Configuration for how the UML should be tweaked
* @param readerClass Class or interface representation
*/
function createPlantUMLCodeForClass(
config: UMLConfig,
readerClass: LightweightClassDefinition,
): string {
function createPlantUMLCodeForClass(config: UMLConfig, readerClass: LightweightClassDefinition): string {
// create the definition header, what type the definition is, it's name and it's inheritance
let model = `${readerClass.type} ${readerClass.name}`;
let model = `${readerClass.modifiers} ${readerClass.name}`;
if (readerClass.typeParameters.length > 0) {
model += `<${readerClass.typeParameters.join(', ')}>`;
if (readerClass.typeParameters?.length ?? 0 > 0) {
model += `<${readerClass.typeParameters!.join(', ')}>`;
}
if (config.showInheritance && readerClass.extendedDefinitions.length > 0) {
if (config.showInheritance && (readerClass.extendedDefinitions?.length ?? 0 > 0)) {
// PlantUML will automatically create links, when using extends
model += ` extends ${readerClass.extendedDefinitions.join(', ')}`;
model += ` extends ${readerClass.extendedDefinitions!.join(', ')}`;
}
if (config.showInheritance && readerClass.implementedDefinitions.length > 0) {
// PlantUML will automatically create links, when using implenents
model += ` implements ${readerClass.implementedDefinitions.join(', ')}`;
if (config.showInheritance && (readerClass.implementedDefinitions?.length ?? 0 > 0)) {
// PlantUML will automatically create links, when using implements
model += ` implements ${readerClass.implementedDefinitions!.join(', ')}`;
}
model += '{';
// add the properties to the definition body
if (config.showProperties) {
for (const property of readerClass.properties) {
forEach(readerClass.properties, property => {
if (property.optional && !config.showOptionalProperties) {
// don't show optional attributes
continue;
return;
}
if (property.inherited && !config.showInheritedProperties) {
/*if (property.inherited && !config.showInheritedProperties) {
// don't show inherited properties
continue;
}
}*/
model += `\n\t${createPropertyLine(property)}`;
}
});
}
// close the definition body
model += '\n}\n';
// add associations from properties with references
for (const property of readerClass.properties) {
forEach(readerClass.properties, property => {
const types: string[] = getReferenceTypes(property.type);
for (const type of types) {
if ( config.showAssociations) {
if (property.inherited && !config.showInheritedProperties) {
if (config.showAssociations) {
/*if (property.inherited && !config.showInheritedProperties) {
continue;
}
}*/
model += `${readerClass.name} -up-> ${type} : ${property.name} >\n`;
}
}
}
});
return model;
}
@@ -255,17 +233,14 @@ function createPlantUMLCodeForClass(
* @param config Configuration for how the UML should be tweaked
* @param readerEnum Enum/-like representation
*/
function createPlantUMLCodeForEnum(
config: UMLConfig,
readerEnum: LightweightEnumDefinition,
): string {
function createPlantUMLCodeForEnum(config: UMLConfig, readerEnum: LightweightAliasDefinition): string {
// create enum header
let model = `enum ${readerEnum.name} {`;
// add values
if (config.showEnumValues) {
for (const value of readerEnum.values) {
forEach(readerEnum.type?.specificationTypes, value => {
model += `\n\t${value.toString()}`;
}
});
}
model += '\n}\n';
@@ -276,7 +251,7 @@ function createPlantUMLCodeForEnum(
* Creates a property PlantUML Line
*/
function createPropertyLine(property: LightweightProperty): string {
const prefix = `${(property.inherited ? '/ ' : '')}${(property.optional ? '? ' : '')}`;
const prefix = `${/*(property.inherited ? '/ ' : */ ''}${property.optional ? '? ' : ''}`;
return `${prefix}${property.name} : ${getFullTypeName(property.type)}`;
return `${prefix}${property.name} : ${expandTypeValue(property.type)}`;
}

View File

@@ -1,56 +0,0 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {LightweightDefinition} from './lightweight-definition';
import {LightweightProperty} from './lightweight-property';
/**
* Represents a class definition
*/
export class LightweightClassDefinition extends LightweightDefinition {
/**
* String values of the extended definitions
*/
public extendedDefinitions: string[];
/**
* String values of the implemented definitions
*/
public implementedDefinitions: string[];
/**
* Properties of the definition
*/
public properties: LightweightProperty[];
/**
* The definition type
* e.g. `interface`/[`abstract`] `class`
*/
public type: string;
/**
* Generic type parameters of this class
*/
public typeParameters: string[];
constructor(name: string, type: string) {
super(name);
this.type = type;
this.properties = [];
this.extendedDefinitions = [];
this.implementedDefinitions = [];
this.typeParameters = [];
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Represents any definition without specifics
*/
export abstract class LightweightDefinition {
/**
* Name of the definiton
*/
public name: string;
constructor(name: string) {
this.name = name;
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {LightweightDefinition} from './lightweight-definition';
/**
* Represents an enum definition
*/
export class LightweightEnumDefinition extends LightweightDefinition {
/**
* Enumeration or union values
*/
public values: string[];
constructor(name: string) {
super(name);
this.values = [];
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {LightweightType} from './lightweight-type';
/**
* Represents a property definition
*/
export class LightweightProperty {
/**
* Is the property inherited from another definition
*/
public inherited: boolean;
/**
* Name of the property
*/
public name: string;
/**
* Is the property marked as optional
*/
public optional: boolean;
/**
* Type of the property
*/
public type: LightweightType;
/**
* Constructor for LightweightProperty
*
* @param name Name of the property
* @param type Type of the property
* @param optional Is the property optional
*/
constructor(name: string, type: LightweightType, optional = true) {
this.name = name;
this.optional = optional;
this.inherited = false;
this.type = type;
}
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Describes an easy to use type definition.
*/
export class LightweightType {
/**
* Contains all types inside of <> brackets
*/
genericsTypes: LightweightType[];
/**
* Does the type have generic-parameters
*/
hasTypeInformation = false;
/**
* Does the type represent an array type
*/
isArray = false;
/**
* Does the type represent a literal type
*/
isLiteral = false;
/**
* Does the type represent a primitive type
*/
isPrimitive = false;
/**
* Does the type contain a reference to
*/
isReference = false;
/**
* Is the type a reflection and not avaiblabe at compile time
*/
isReflection = false;
/**
* Does the type have type parameters
*/
isTyped = false;
/**
* Is the type a typed parameter
*/
isTypeParameter = false;
/**
* Is the type a union type
*/
isUnion = false;
/**
* Name of the type
*/
name: string;
/**
* Type specifications, if the type is combined by either an array, union or a typeOperator
*/
specificationTypes: LightweightType[];
constructor() {
this.specificationTypes = [];
this.genericsTypes = [];
this.name = '';
}
}

View File

@@ -1,471 +0,0 @@
/*
* Copyright (C) 2019 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Logger} from '@openstapps/logger';
import {
ArrayType,
ConditionalType,
DeclarationReflection,
IntrinsicType,
ProjectReflection,
QueryType,
ReferenceType,
ReflectionKind,
ReflectionType,
StringLiteralType,
Type,
TypeOperatorType,
TypeParameterType,
UnionType,
} from 'typedoc/dist/lib/models';
import {getFullTypeName} from '../common';
import {LightweightClassDefinition} from './model/lightweight-class-definition';
import {LightweightDefinition} from './model/lightweight-definition';
import {LightweightEnumDefinition} from './model/lightweight-enum-definition';
import {LightweightProperty} from './model/lightweight-property';
import {LightweightType} from './model/lightweight-type';
/**
* Reads the reflection model from typedoc and converts it into a flatter, easier to handle model
*
* @param srcPath Path to source file directory
*/
export function readDefinitions(projectReflection: ProjectReflection): LightweightDefinition[] {
const definitions: LightweightDefinition[] = [];
// define known types and categorize them
const enumLike: string[] = ['Type alias', 'Enumeration'];
const classLike: string[] = ['Class', 'Interface'];
const unused: string[] = ['Function', 'Object literal', 'Variable'];
// children need to be not undefined, if they are return empty
if (typeof projectReflection.children === 'undefined') {
return [];
}
for (const module of projectReflection.children) {
if (Array.isArray(module.children) && module.children.length > 0) {
// iterate over class and enum declarations
for (const type of module.children) {
// only if kindString is set
if (typeof type.kindString !== 'undefined') {
// check if declaration is enum
if (classLike.includes(type.kindString)) {
definitions.push(readAsClassDefinition(type));
} else if (enumLike.includes(type.kindString)) {
definitions.push(readAsEnumDefinition(type));
} else if (unused.includes(type.kindString)) {
Logger.info(`Unconverted ${type.kindString} : ${type.name}`);
} else {
Logger.log(
`Uncaught declaration type (${type.kindString}) : ${type.name}`,
);
}
}
}
}
}
return definitions;
}
/**
* Transforms the declaration into a `LightweightClassDefinition`
*
* @param declaration declaration
*/
export function readAsEnumDefinition(
declaration: DeclarationReflection,
): LightweightEnumDefinition {
// init enum definition
const enumDefinition: LightweightEnumDefinition = new LightweightEnumDefinition(
declaration.name,
);
// get enum values according to type
if (declaration.kindString === 'Enumeration' && typeof declaration.children !== 'undefined') {
// standard enumeration
for (const child of declaration.children) {
if (child.kindString === 'Enumeration member') {
let value = child.name;
if (typeof child.defaultValue !== 'undefined') {
value = `${value} = ${child.defaultValue}`;
}
enumDefinition.values.push(value);
} else {
Logger.log(
"Every enumeration member should be an 'EnumerationMemberType'",
);
}
}
} else if (
declaration.kindString === 'Type alias' &&
typeof declaration.type !== 'undefined'
) {
// enum like declaration
try {
const a = readTypeInformation(declaration.type);
enumDefinition.values = enumDefinition.values.concat(
getTypeInformation(a),
);
} catch (e) {
Logger.warn(
`Could not read the light type for ${declaration.name}. ${e}`,
);
}
}
return enumDefinition;
}
/**
* Used for enumrations to get the type value
*/
function getTypeInformation(type: LightweightType): string[] {
const values: string[] = [];
if (!type.hasTypeInformation) {
for (const specificType of type.specificationTypes) {
for (const value of getTypeInformation(specificType)) {
values.push(value);
}
}
} else {
values.push(type.name);
}
return values;
}
/**
* Transforms the declaration into a `LightweightClassDefinition`
*
* @param declaration declaration
*/
export function readAsClassDefinition(
declaration: DeclarationReflection,
): LightweightClassDefinition {
let type = typeof declaration.kindString !== 'undefined' ? declaration.kindString.toLowerCase() : '';
type = (declaration.flags.isAbstract ? 'abstract ' : '') + type;
const classDefinition: LightweightClassDefinition = new LightweightClassDefinition(
declaration.name,
type,
);
// get generic types
if (typeof declaration.typeParameters !== 'undefined') {
const typeParameters: string[] = [];
declaration.typeParameters.forEach((typeParameter) =>
typeParameters.push(typeParameter.name),
);
classDefinition.typeParameters = typeParameters;
}
// extracts extended types of the declaration
if (typeof declaration.extendedTypes !== 'undefined') {
for (const extType of declaration.extendedTypes) {
classDefinition.extendedDefinitions.push((extType as ReferenceType).name);
}
}
// extracts implemented types of the declaration
// HINT: typedoc automatically adds inherited interfaces to the declaration directly
if (typeof declaration.implementedTypes !== 'undefined') {
for (const implType of declaration.implementedTypes) {
classDefinition.implementedDefinitions.push(
(implType as ReferenceType).name,
);
}
}
if (typeof declaration.children !== 'undefined') {
for (const child of declaration.getChildrenByKind(
ReflectionKind.Property,
)) {
try {
if (typeof child.type === 'undefined') {
throw new Error();
}
const myType: LightweightType = readTypeInformation(child.type);
const property = new LightweightProperty(child.name, myType);
const flags = child.flags;
if (flags.isOptional !== undefined) {
property.optional = flags.isOptional as boolean;
property.inherited = !(
child.inheritedFrom === undefined || child.inheritedFrom === null
);
}
classDefinition.properties.push(property);
} catch (e) {
Logger.warn(e);
}
}
}
return classDefinition;
}
/**
* The structure of reflection type has a huge overhead
* This method and all submethods will convert these types in easier to process Types
*
* @param declarationType Type to be converted
*/
function readTypeInformation(declarationType: Type): LightweightType {
if (declarationType instanceof ReflectionType) {
return readAsReflectionType(declarationType);
}
if (declarationType instanceof TypeOperatorType) {
return readAsTypeOperatorType(declarationType);
}
if (declarationType instanceof TypeParameterType) {
return readAsTypeParameterType(declarationType);
}
if (declarationType instanceof IntrinsicType) {
return readAsIntrinsicType(declarationType);
}
if (declarationType instanceof StringLiteralType) {
return readAsStringLiteralType(declarationType);
}
if (declarationType instanceof ReferenceType) {
return readAsReferenceType(declarationType);
}
if (declarationType instanceof ArrayType) {
return readAsArrayType(declarationType);
}
if (declarationType instanceof UnionType) {
return readAsUnionType(declarationType);
}
if (declarationType instanceof QueryType) {
return readAsQueryType(declarationType);
}
if (declarationType instanceof ConditionalType) {
return readAsConditionalType(declarationType);
}
throw new Error(`Could not read type ${declarationType.type}`);
}
/**
* Conversion method for ConditionalTypes
*
* @param _type Type to be converted
*/
function readAsConditionalType(_type: ConditionalType): LightweightType {
const returnType: LightweightType = new LightweightType();
returnType.specificationTypes = [];
returnType.name = getFullTypeName(returnType);
returnType.isUnion = true;
return returnType;
}
/**
* Conversion method for QueryTypes
*
* @param type Type to be converted
*/
function readAsQueryType(type: QueryType): LightweightType {
const out = readAsReferenceType(type.queryType);
out.isReference = true;
return out;
}
/**
* Conversion method for IntrinsicType's
*
* e.g. remainingAttendeeCapacity?: number;
*
* @param type Type to be converted
*/
function readAsIntrinsicType(type: IntrinsicType): LightweightType {
const easyType: LightweightType = new LightweightType();
easyType.name = type.name;
easyType.isPrimitive = true;
easyType.hasTypeInformation = true;
return easyType;
}
/**
* Conversion method for StringLiteralType's
*
* e.g. inputType: 'multipleChoice';
*
* @param type Type to be converted
*/
function readAsStringLiteralType(type: StringLiteralType): LightweightType {
const returnType: LightweightType = new LightweightType();
returnType.name = type.value;
returnType.isLiteral = true;
returnType.hasTypeInformation = true;
return returnType;
}
/**
* Conversion method for ReferenceType's
*
* Everything that is a user or API designed definition and not a primitive type or core-language feature.
*
* e.g. publishers?: Array<SCPersonWithoutReferences | SCOrganizationWithoutReferences>;
*
* Array, SCPersonWithoutReferences and SCOrganizationWithoutReferences will be recognized as reference types!
*
* @param type Type to be converted
*/
function readAsReferenceType(type: ReferenceType): LightweightType {
const returnType: LightweightType = new LightweightType();
returnType.name = type.name;
if (type.typeArguments !== undefined && type.typeArguments.length > 0) {
const typeArguments: LightweightType[] = [];
for (const value of type.typeArguments) {
typeArguments.push(readTypeInformation(value));
}
returnType.isTyped = true;
returnType.genericsTypes = typeArguments;
}
if (type.reflection !== undefined && type.reflection !== null) {
const tempTypeReflection = type.reflection as DeclarationReflection;
// interfaces and classes in a type are a sink, since their declaration are defined elsewhere
if (
typeof tempTypeReflection.kindString !== 'undefined' &&
['Interface', 'Class', 'Enumeration', 'Type alias'].includes(
tempTypeReflection.kindString)) {
returnType.isReference = true;
}
}
returnType.hasTypeInformation = true;
return returnType;
}
/**
* Conversion method for ArrayType's
*
* The actual type of the array is stored in the first element of specificationTypes.
*
* e.g. articleBody?: string[];
*
* @param type Type to be converted
*/
function readAsArrayType(type: ArrayType): LightweightType {
const returnType: LightweightType = new LightweightType();
const typeOfArray: LightweightType = readTypeInformation(type.elementType);
returnType.name = getFullTypeName(typeOfArray);
returnType.specificationTypes = [typeOfArray];
returnType.isArray = true;
return returnType;
}
/**
* Conversion method for UnionType's
*
* The Union-LightType store the single types of the union inside a
* separate LightType inside specificationTypes.
*
* e.g. maintainer?: SCPerson | SCOrganization;
*
* @param type Type to be converted
*/
function readAsUnionType(type: UnionType): LightweightType {
const returnType: LightweightType = new LightweightType();
const typesOfUnion: LightweightType[] = [];
for (const value of type.types) {
typesOfUnion.push(readTypeInformation(value));
}
returnType.specificationTypes = typesOfUnion;
returnType.name = getFullTypeName(returnType);
returnType.isUnion = true;
return returnType;
}
/**
* Conversion method for ReflectionType's
*
* The explicit type is not contained in reflection!
* It might be possible to get the structure of type by reading tempType.decoration.children,
* but this structure is currently not supported in the data-model.
*
* e.g. categorySpecificValues?: { [s: string]: U };
*
* @param type Type to be converted
*/
function readAsReflectionType(type: ReflectionType): LightweightType {
const returnType: LightweightType = new LightweightType();
if (typeof type.declaration.sources !== 'undefined') {
const src = type.declaration.sources[0];
Logger.warn(
`${src.line} : ${src.fileName}: Reflection Type not recognized. Refactoring to explicit class is advised.`,
);
}
returnType.name = 'object';
returnType.isReflection = true;
return returnType;
}
/**
* Conversion method for TypeOperatorType's
*
* This type is similar to reflection, that the actual type can only be evaluated at runtime.
*
* e.g. universityRole: keyof SCSportCoursePriceGroup;
*
* @param type Type to be converted
*/
function readAsTypeOperatorType(type: TypeOperatorType): LightweightType {
const returnType: LightweightType = new LightweightType();
const typeOf: LightweightType = readTypeInformation(type.target);
returnType.name = `keyof ${getFullTypeName(typeOf)}`;
returnType.specificationTypes = [typeOf];
// can't be traced deeper! so might as well be a primitive
returnType.isPrimitive = true;
returnType.hasTypeInformation = true;
return returnType;
}
/**
* Conversion method for TypeParameterType's
*
* Should only be called in generic classes/interfaces, when a property is
* referencing the generic-type.
*
* e.g. prices?: T;
*
* Does not match on Arrays of the generic type. Those will be matched with ArrayType.
*
* @param type Needs to be a TypeParameterType
*/
function readAsTypeParameterType(type: TypeParameterType): LightweightType {
const returnType: LightweightType = new LightweightType();
returnType.name = type.name;
returnType.isTypeParameter = true;
returnType.hasTypeInformation = true;
return returnType;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 StApps
* Copyright (C) 2021 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.