mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-09 19:22:51 +00:00
feat: add the uml generator
This commit is contained in:
104
src/cli.ts
104
src/cli.ts
@@ -16,10 +16,22 @@ import {Logger} from '@openstapps/logger';
|
||||
import * as commander from 'commander';
|
||||
import {existsSync, readFileSync, writeFileSync} from 'fs';
|
||||
import {join, resolve} from 'path';
|
||||
import {getProjectReflection, mkdirPromisified, readFilePromisified} from './common';
|
||||
import {
|
||||
getProjectReflection,
|
||||
mkdirPromisified,
|
||||
readFilePromisified,
|
||||
toArray,
|
||||
} from './common';
|
||||
import {pack} from './pack';
|
||||
import {gatherRouteInformation, generateDocumentationForRoute, getNodeMetaInformationMap} from './routes';
|
||||
import {
|
||||
gatherRouteInformation,
|
||||
generateDocumentationForRoute,
|
||||
getNodeMetaInformationMap,
|
||||
} from './routes';
|
||||
import {Converter, getValidatableTypesFromReflection} from './schema';
|
||||
import {createDiagram, createDiagramFromString} from './uml/createDiagram';
|
||||
import {readDefinitions} from './uml/readDefinitions';
|
||||
import {UMLConfig} from './uml/umlConfig';
|
||||
import {validateFiles, writeReport} from './validate';
|
||||
|
||||
// handle unhandled promise rejections
|
||||
@@ -53,7 +65,10 @@ commander
|
||||
|
||||
// generate documentation for all routes
|
||||
routes.forEach((routeWithMetaInformation) => {
|
||||
output += generateDocumentationForRoute(routeWithMetaInformation, getNodeMetaInformationMap(projectReflection));
|
||||
output += generateDocumentationForRoute(
|
||||
routeWithMetaInformation,
|
||||
getNodeMetaInformationMap(projectReflection),
|
||||
);
|
||||
});
|
||||
|
||||
// write documentation to file
|
||||
@@ -76,7 +91,9 @@ commander
|
||||
const projectReflection = getProjectReflection(srcPath);
|
||||
|
||||
// get validatable types
|
||||
const validatableTypes = getValidatableTypesFromReflection(projectReflection);
|
||||
const validatableTypes = getValidatableTypesFromReflection(
|
||||
projectReflection,
|
||||
);
|
||||
|
||||
Logger.info(`Found ${validatableTypes.length} type(s) to generate schemas for.`);
|
||||
|
||||
@@ -152,14 +169,85 @@ commander
|
||||
}
|
||||
});
|
||||
|
||||
commander.command('pack').action(async () => {
|
||||
await pack();
|
||||
});
|
||||
|
||||
commander
|
||||
.command('pack')
|
||||
.action(async () => {
|
||||
await pack();
|
||||
.command('plantuml <srcPath> <plantumlserver>')
|
||||
.option(
|
||||
'--definitions <definitions>',
|
||||
'Shows these specific definitions (class or enum)',
|
||||
toArray,
|
||||
)
|
||||
.option('--showAssociations', 'Shows associations of classes')
|
||||
.option(
|
||||
'--showInheritance',
|
||||
'Shows extensions and implementations of classes',
|
||||
)
|
||||
.option('--showEnumValues', 'Show enum values')
|
||||
.option('--showProperties', 'Show attributes')
|
||||
.option(
|
||||
'--showInheritedProperties',
|
||||
'Shows inherited attributes, needs --showProperties',
|
||||
)
|
||||
.option(
|
||||
'--showOptionalProperties',
|
||||
'Shows optional attributes and relations, needs --showProperties',
|
||||
)
|
||||
.option(
|
||||
'--excludeExternals',
|
||||
'Exclude external definitions',
|
||||
)
|
||||
.action(async (relativeSrcPath, plantumlserver, options) => {
|
||||
const plantUmlConfig: UMLConfig = {
|
||||
definitions:
|
||||
typeof options.definitions !== 'undefined' ? options.definitions : [],
|
||||
showAssociations:
|
||||
typeof options.showAssociations !== 'undefined'
|
||||
? options.showAssociations
|
||||
: false,
|
||||
showEnumValues:
|
||||
typeof options.showEnumValues !== 'undefined'
|
||||
? options.showEnumValues
|
||||
: false,
|
||||
showInheritance:
|
||||
typeof options.showInheritance !== 'undefined'
|
||||
? options.showInheritance
|
||||
: false,
|
||||
showInheritedProperties:
|
||||
typeof options.showInheritedProperties !== 'undefined'
|
||||
? options.showInheritedProperties
|
||||
: false,
|
||||
showOptionalProperties:
|
||||
typeof options.showOptionalProperties !== 'undefined'
|
||||
? options.showOptionalProperties
|
||||
: false,
|
||||
showProperties:
|
||||
typeof options.showProperties !== 'undefined'
|
||||
? options.showEnumValues
|
||||
: false,
|
||||
};
|
||||
|
||||
Logger.log(`PlantUML options: ${JSON.stringify(plantUmlConfig)}`);
|
||||
|
||||
const srcPath = resolve(relativeSrcPath);
|
||||
|
||||
const projectReflection = getProjectReflection(srcPath, !options.excludeExternals ? false : true);
|
||||
|
||||
const definitions = readDefinitions(projectReflection);
|
||||
|
||||
await createDiagram(definitions, plantUmlConfig, plantumlserver);
|
||||
});
|
||||
|
||||
commander
|
||||
.parse(process.argv);
|
||||
.command('plantuml-file <file> <plantumlserver>')
|
||||
.action(async (file: string, plantumlserver: string) => {
|
||||
const fileContent = readFileSync(resolve(file)).toString();
|
||||
await createDiagramFromString(fileContent, plantumlserver);
|
||||
});
|
||||
|
||||
commander.parse(process.argv);
|
||||
|
||||
if (commander.args.length < 1) {
|
||||
commander.outputHelp();
|
||||
|
||||
@@ -21,6 +21,7 @@ import {join, sep} from 'path';
|
||||
import {Definition} from 'ts-json-schema-generator';
|
||||
import {Application, ProjectReflection} from 'typedoc';
|
||||
import {promisify} from 'util';
|
||||
import {LightweightType} from './uml/model/LightweightType';
|
||||
|
||||
export const globPromisified = promisify(glob);
|
||||
export const mkdirPromisified = promisify(mkdir);
|
||||
@@ -142,14 +143,14 @@ export interface ExpectableValidationErrors {
|
||||
*
|
||||
* @param srcPath Path to get reflection from
|
||||
*/
|
||||
export function getProjectReflection(srcPath: PathLike): ProjectReflection {
|
||||
export function getProjectReflection(srcPath: PathLike, excludeExternals: boolean = true): ProjectReflection {
|
||||
Logger.info(`Generating project reflection for ${srcPath.toString()}.`);
|
||||
|
||||
const tsconfigPath = getTsconfigPath(srcPath.toString());
|
||||
|
||||
// initialize new Typedoc application
|
||||
const app = new Application({
|
||||
excludeExternals: true,
|
||||
excludeExternals: excludeExternals,
|
||||
includeDeclarations: true,
|
||||
module: 'commonjs',
|
||||
tsconfig: join(tsconfigPath, 'tsconfig.json'),
|
||||
@@ -178,7 +179,9 @@ export function getProjectReflection(srcPath: PathLike): ProjectReflection {
|
||||
*
|
||||
* @param schema Schema to check
|
||||
*/
|
||||
export function isSchemaWithDefinitions(schema: JSONSchema): schema is SchemaWithDefinitions {
|
||||
export function isSchemaWithDefinitions(
|
||||
schema: JSONSchema,
|
||||
): schema is SchemaWithDefinitions {
|
||||
return typeof schema.definitions !== 'undefined';
|
||||
}
|
||||
|
||||
@@ -212,7 +215,9 @@ export function getTsconfigPath(startPath: string): string {
|
||||
// repeat until a tsconfig.json is found
|
||||
while (!existsSync(join(tsconfigPath, 'tsconfig.json'))) {
|
||||
if (tsconfigPath === root) {
|
||||
throw new Error(`Reached file system root ${root} while searching for 'tsconfig.json' in ${startPath}!`);
|
||||
throw new Error(
|
||||
`Reached file system root ${root} while searching for 'tsconfig.json' in ${startPath}!`,
|
||||
);
|
||||
}
|
||||
|
||||
// pop last directory
|
||||
@@ -225,3 +230,51 @@ export function getTsconfigPath(startPath: string): string {
|
||||
|
||||
return tsconfigPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a comma seperated string into a string array
|
||||
*
|
||||
* @param val Comma seperated string
|
||||
*/
|
||||
export function toArray(val: string): string[] {
|
||||
return val.split(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the full name of a lightweight type recursivly
|
||||
*
|
||||
* @param type Type to get the full name of
|
||||
*/
|
||||
export function getFullTypeName(type: LightweightType): string {
|
||||
// init name
|
||||
let fullName: string = type.name;
|
||||
if (type.isTypeParameter) {
|
||||
// type parameters are a sink
|
||||
return fullName;
|
||||
}
|
||||
if (type.isLiteral) {
|
||||
// literals are a sink
|
||||
return "'" + fullName + "'";
|
||||
}
|
||||
if (type.isUnion && type.specificationTypes.length > 0) {
|
||||
const tempNames: string[] = [];
|
||||
for (const easyType of type.specificationTypes) {
|
||||
tempNames.push(getFullTypeName(easyType));
|
||||
}
|
||||
// since unions can't be applied to other types, it is a sink.
|
||||
return tempNames.join(' | ');
|
||||
}
|
||||
// check if type is generic and has a type attached
|
||||
if (type.isTyped && type.genericsTypes.length > 0) {
|
||||
const tempNames: string[] = [];
|
||||
for (const easyType of type.genericsTypes) {
|
||||
tempNames.push(getFullTypeName(easyType));
|
||||
}
|
||||
fullName += '<' + tempNames.join(', ') + '>';
|
||||
}
|
||||
// check if type is array
|
||||
if (type.isArray) {
|
||||
fullName += '[]';
|
||||
}
|
||||
return fullName;
|
||||
}
|
||||
|
||||
274
src/uml/createDiagram.ts
Normal file
274
src/uml/createDiagram.ts
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* 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 {createWriteStream} from 'fs';
|
||||
import * as request from 'got';
|
||||
import {getFullTypeName} from '../common';
|
||||
import {LightweightClassDefinition} from './model/LightweightClassDefinition';
|
||||
import {LightweightDefinition} from './model/LightweightDefinition';
|
||||
import {LightweightEnumDefinition} from './model/LightweightEnumDefinition';
|
||||
import {LightweightProperty} from './model/LightweightProperty';
|
||||
import {LightweightType} from './model/LightweightType';
|
||||
import {UMLConfig} from './umlConfig';
|
||||
|
||||
/**
|
||||
* Converts the lightweight class/enum definitions according to the configuration,
|
||||
* 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 config contains information on how the PlantUML should be generated
|
||||
* @param plantUmlBaseURL Hostname of the PlantUML-Server
|
||||
*/
|
||||
export async function createDiagram(
|
||||
definitions: LightweightDefinition[],
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
// when providing definitions and either showing associations or inheritance the
|
||||
// inherited definitions will be added automatically
|
||||
if (config.showInheritance) {
|
||||
const inheritedDefinitions = gatherTypeAssociations(
|
||||
definitions,
|
||||
config.definitions,
|
||||
);
|
||||
|
||||
config.definitions = config.definitions.concat(inheritedDefinitions);
|
||||
}
|
||||
|
||||
let modelPlantUMLCode: string = '';
|
||||
// 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: string = '';
|
||||
if (definition instanceof LightweightClassDefinition) {
|
||||
definitionPlantUMLCode = createPlantUMLCodeForClass(config, definition);
|
||||
} else if (definition instanceof LightweightEnumDefinition) {
|
||||
definitionPlantUMLCode = createPlantUMLCodeForEnum(config, definition);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
modelPlantUMLCode += definitionPlantUMLCode;
|
||||
}
|
||||
|
||||
return await createDiagramFromString(modelPlantUMLCode, plantUmlBaseURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will encode the plantuml code and post the code to the plantuml server
|
||||
* The server will then parse the code and create a corresponding diagram
|
||||
*
|
||||
* @param modelPlantUMLCode
|
||||
*/
|
||||
export async function createDiagramFromString(modelPlantUMLCode: string, plantUmlBaseURL: string) {
|
||||
const plantumlEncoder = require('plantuml-encoder');
|
||||
const plantUMLCode = plantumlEncoder.encode(modelPlantUMLCode);
|
||||
const url = `${plantUmlBaseURL}/svg/${plantUMLCode}`;
|
||||
let response;
|
||||
try {
|
||||
response = await request(url);
|
||||
if (response.statusCode !== 200) {
|
||||
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;
|
||||
}
|
||||
const fileName: string = `Diagram-${new Date().toISOString()}.svg`;
|
||||
try {
|
||||
createWriteStream(fileName).write(response.body);
|
||||
Logger.log(`Writen data to file: ${fileName}`);
|
||||
} catch (e) {
|
||||
throw new Error('Could not write file. Are you missing permissions?');
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursivly iterates over all types, to find implemented generic types and parents
|
||||
*
|
||||
* @param definitions all type definitons of the project
|
||||
* @param abstractionNames currently known string values of inherited classes
|
||||
*/
|
||||
function gatherTypeAssociations(
|
||||
definitions: LightweightDefinition[],
|
||||
abstractionNames: string[],
|
||||
): string[] {
|
||||
let abstractions: string[] = [];
|
||||
for (const name of abstractionNames) {
|
||||
const declaration = definitions.find(
|
||||
(definition) => definition.name === name,
|
||||
);
|
||||
if (declaration instanceof LightweightClassDefinition) {
|
||||
const currentAbstractions: string[] = declaration.extendedDefinitions.concat(
|
||||
declaration.implementedDefinitions,
|
||||
);
|
||||
|
||||
abstractions = abstractions.concat(currentAbstractions);
|
||||
abstractions = abstractions.concat(
|
||||
gatherTypeAssociations(definitions, currentAbstractions),
|
||||
);
|
||||
}
|
||||
}
|
||||
return abstractions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all reference information of this type.
|
||||
*
|
||||
* Reference information is everything that is indirectly referencing a type or class by name.
|
||||
*
|
||||
* @param type Type with references to other types
|
||||
*/
|
||||
function getReferenceTypes(type: LightweightType): string[] {
|
||||
const types: string[] = [];
|
||||
if (type.isReference) {
|
||||
types.push(type.name);
|
||||
}
|
||||
if (type.isTyped && type.genericsTypes.length > 0) {
|
||||
for (const specificType of type.genericsTypes) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Plant UML code according to the config for the provided class
|
||||
*
|
||||
* @param config Configuration for how the UML should be tweaked
|
||||
* @param readerClass Class or interface representation
|
||||
*/
|
||||
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: string = `${readerClass.type} ${readerClass.name}`;
|
||||
|
||||
if (readerClass.typeParameters.length > 0) {
|
||||
model += `<${readerClass.typeParameters.join(', ')}>`;
|
||||
}
|
||||
|
||||
if (config.showInheritance && readerClass.extendedDefinitions.length > 0) {
|
||||
// PlantUML will automatically create links, when using extends
|
||||
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(', ')}`;
|
||||
}
|
||||
model += '{';
|
||||
|
||||
// add the properties to the definition body
|
||||
if (config.showProperties) {
|
||||
for (const property of readerClass.properties) {
|
||||
if (property.optional && !config.showOptionalProperties) {
|
||||
// don't show optional attributes
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
const types: string[] = getReferenceTypes(property.type);
|
||||
for (const type of types) {
|
||||
if ( config.showAssociations) {
|
||||
if (property.inherited && !config.showInheritedProperties) {
|
||||
continue;
|
||||
}
|
||||
model += `${readerClass.name} -up-> ${type} : ${property.name} >\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates PlantUML code according to the config for the provided enum/-like definition
|
||||
*
|
||||
* @param config Configuration for how the UML should be tweaked
|
||||
* @param readerEnum Enum/-like representation
|
||||
*/
|
||||
function createPlantUMLCodeForEnum(
|
||||
config: UMLConfig,
|
||||
readerEnum: LightweightEnumDefinition,
|
||||
): string {
|
||||
// create enum header
|
||||
let model: string = `enum ${readerEnum.name} {`;
|
||||
// add values
|
||||
if (config.showEnumValues) {
|
||||
for (const value of readerEnum.values) {
|
||||
model += `\n\t${value.toString()}`;
|
||||
}
|
||||
}
|
||||
model += '\n}\n';
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a property PlantUML Line
|
||||
*/
|
||||
function createPropertyLine(property: LightweightProperty): string {
|
||||
return (
|
||||
(property.inherited ? '/ ' : '') +
|
||||
(property.optional ? '?' : '') +
|
||||
property.name +
|
||||
' : ' +
|
||||
getFullTypeName(property.type)
|
||||
);
|
||||
}
|
||||
56
src/uml/model/LightweightClassDefinition.ts
Normal file
56
src/uml/model/LightweightClassDefinition.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 './LightweightDefinition';
|
||||
import {LightweightProperty} from './LightweightProperty';
|
||||
/**
|
||||
* 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 = [];
|
||||
}
|
||||
}
|
||||
28
src/uml/model/LightweightDefinition.ts
Normal file
28
src/uml/model/LightweightDefinition.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
30
src/uml/model/LightweightEnumDefinition.ts
Normal file
30
src/uml/model/LightweightEnumDefinition.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 './LightweightDefinition';
|
||||
/**
|
||||
* Represents an enum definition
|
||||
*/
|
||||
export class LightweightEnumDefinition extends LightweightDefinition {
|
||||
/**
|
||||
* Enumeration or union values
|
||||
*/
|
||||
public values: string[];
|
||||
|
||||
constructor(name: string) {
|
||||
super(name);
|
||||
this.values = [];
|
||||
}
|
||||
}
|
||||
54
src/uml/model/LightweightProperty.ts
Normal file
54
src/uml/model/LightweightProperty.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 './LightweightType';
|
||||
|
||||
/**
|
||||
* 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: boolean = true) {
|
||||
this.name = name;
|
||||
this.optional = optional;
|
||||
this.inherited = false;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
85
src/uml/model/LightweightType.ts
Normal file
85
src/uml/model/LightweightType.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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: boolean = false;
|
||||
|
||||
/**
|
||||
* Does the type represent an array type
|
||||
*/
|
||||
isArray: boolean = false;
|
||||
|
||||
/**
|
||||
* Does the type represent a literal type
|
||||
*/
|
||||
isLiteral: boolean = false;
|
||||
|
||||
/**
|
||||
* Does the type represent a primitive type
|
||||
*/
|
||||
isPrimitive: boolean = false;
|
||||
|
||||
/**
|
||||
* Does the type contain a reference to
|
||||
*/
|
||||
isReference: boolean = false;
|
||||
|
||||
/**
|
||||
* Is the type a reflection and not avaiblabe at compile time
|
||||
*/
|
||||
isReflection: boolean = false;
|
||||
|
||||
/**
|
||||
* Does the type have type parameters
|
||||
*/
|
||||
isTyped: boolean = false;
|
||||
|
||||
/**
|
||||
* Is the type a typed parameter
|
||||
*/
|
||||
isTypeParameter: boolean = false;
|
||||
|
||||
/**
|
||||
* Is the type a union type
|
||||
*/
|
||||
isUnion: boolean = 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 = '';
|
||||
}
|
||||
}
|
||||
423
src/uml/readDefinitions.ts
Normal file
423
src/uml/readDefinitions.ts
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* 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,
|
||||
DeclarationReflection,
|
||||
IntrinsicType,
|
||||
ProjectReflection,
|
||||
ReferenceType,
|
||||
ReflectionKind,
|
||||
ReflectionType,
|
||||
StringLiteralType,
|
||||
Type,
|
||||
TypeOperatorType,
|
||||
TypeParameterType,
|
||||
UnionType,
|
||||
} from 'typedoc/dist/lib/models';
|
||||
import {getFullTypeName} from '../common';
|
||||
import {LightweightClassDefinition} from './model/LightweightClassDefinition';
|
||||
import {LightweightDefinition} from './model/LightweightDefinition';
|
||||
import {LightweightEnumDefinition} from './model/LightweightEnumDefinition';
|
||||
import {LightweightProperty} from './model/LightweightProperty';
|
||||
import {LightweightType} from './model/LightweightType';
|
||||
|
||||
/**
|
||||
* 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' && declaration.children) {
|
||||
// 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 = declaration.kindString ? 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);
|
||||
} else if (declarationType instanceof TypeOperatorType) {
|
||||
return readAsTypeOperatorType(declarationType);
|
||||
} else if (declarationType instanceof TypeParameterType) {
|
||||
return readAsTypeParameterType(declarationType);
|
||||
} else if (declarationType instanceof IntrinsicType) {
|
||||
return readAsIntrinsicType(declarationType);
|
||||
} else if (declarationType instanceof StringLiteralType) {
|
||||
return readAsStringLiteralType(declarationType);
|
||||
} else if (declarationType instanceof ReferenceType) {
|
||||
return readAsReferenceType(declarationType);
|
||||
} else if (declarationType instanceof ArrayType) {
|
||||
return readAsArrayType(declarationType);
|
||||
} else if (declarationType instanceof UnionType) {
|
||||
return readAsUnionType(declarationType);
|
||||
} else {
|
||||
throw new Error(`Could not read type ${declarationType.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (
|
||||
tempTypeReflection.kindString &&
|
||||
['Interface', 'Class', 'Enumeration', 'Type alias'].indexOf(
|
||||
tempTypeReflection.kindString,
|
||||
) > -1
|
||||
) {
|
||||
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 (type.declaration.sources) {
|
||||
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;
|
||||
}
|
||||
54
src/uml/umlConfig.ts
Normal file
54
src/uml/umlConfig.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds configuration information of how the UML code should be build
|
||||
*/
|
||||
export interface UMLConfig {
|
||||
/**
|
||||
* Defines which definitions are shown
|
||||
*/
|
||||
definitions: string[];
|
||||
|
||||
/**
|
||||
* Should the associations between definitions be shown
|
||||
*/
|
||||
showAssociations: boolean;
|
||||
|
||||
/**
|
||||
* Should enum/-like values be shown
|
||||
*/
|
||||
showEnumValues: boolean;
|
||||
|
||||
/**
|
||||
* Should the inheritance be shown
|
||||
*/
|
||||
showInheritance: boolean;
|
||||
|
||||
/**
|
||||
* Should the inherited properties be shown
|
||||
*/
|
||||
showInheritedProperties: boolean;
|
||||
|
||||
/**
|
||||
* Should optional properties be shown
|
||||
*/
|
||||
showOptionalProperties: boolean;
|
||||
|
||||
/**
|
||||
* Should properties be shown
|
||||
*/
|
||||
showProperties: boolean;
|
||||
}
|
||||
Reference in New Issue
Block a user