/****************************************************************************** * Copyright 2022 TypeFox GmbH * This program and the accompanying materials are made available under the * terms of the MIT License, which is available in the project root. ******************************************************************************/ import type { Interface, Type, TypeDefinition, ValueLiteral } from '../../../languages/generated/ast.js'; import type { LangiumCoreServices } from '../../../index.js'; import { isArrayLiteral, isBooleanLiteral } from '../../../languages/generated/ast.js'; import type { PlainAstTypes, PlainInterface, PlainProperty, PlainPropertyDefaultValue, PlainPropertyType, PlainUnion } from './plain-types.js'; import { isArrayType, isReferenceType, isUnionType, isSimpleType } from '../../../languages/generated/ast.js'; import { getTypeNameWithoutError, isPrimitiveGrammarType } from '../../internal-grammar-util.js'; import { getTypeName } from '../../../utils/grammar-utils.js'; export function collectDeclaredTypes(interfaces: Interface[], unions: Type[], services?: LangiumCoreServices): PlainAstTypes { const commentProvider = services?.documentation.CommentProvider; const declaredTypes: PlainAstTypes = { unions: [], interfaces: [] }; // add interfaces for (const type of interfaces) { const properties: PlainProperty[] = []; for (const attribute of type.attributes) { const property: PlainProperty = { name: attribute.name, optional: attribute.isOptional, astNodes: new Set([attribute]), type: typeDefinitionToPropertyType(attribute.type), comment: commentProvider?.getComment(attribute) }; if (attribute.defaultValue) { property.defaultValue = toPropertyDefaultValue(attribute.defaultValue); } properties.push(property); } const superTypes = new Set(); for (const superType of type.superTypes) { if (superType.ref) { superTypes.add(getTypeName(superType.ref)); } } const interfaceType: PlainInterface = { name: type.name, declared: true, abstract: false, properties: properties, superTypes: superTypes, subTypes: new Set(), comment: commentProvider?.getComment(type), }; declaredTypes.interfaces.push(interfaceType); } // add types for (const union of unions) { const unionType: PlainUnion = { name: union.name, declared: true, type: typeDefinitionToPropertyType(union.type), superTypes: new Set(), subTypes: new Set(), comment: commentProvider?.getComment(union), }; declaredTypes.unions.push(unionType); } return declaredTypes; } function toPropertyDefaultValue(literal: ValueLiteral): PlainPropertyDefaultValue { if (isBooleanLiteral(literal)) { return literal.true; } else if (isArrayLiteral(literal)) { return literal.elements.map(toPropertyDefaultValue); } else { return literal.value; } } export function typeDefinitionToPropertyType(type: TypeDefinition): PlainPropertyType { if (isArrayType(type)) { return { elementType: typeDefinitionToPropertyType(type.elementType) }; } else if (isReferenceType(type)) { return { referenceType: typeDefinitionToPropertyType(type.referenceType), isMulti: type.isMulti, isSingle: !type.isMulti }; } else if (isUnionType(type)) { return { types: type.types.map(typeDefinitionToPropertyType) }; } else if (isSimpleType(type)) { let value: string | undefined; if (type.primitiveType) { value = type.primitiveType; return { primitive: value }; } else if (type.stringType) { value = type.stringType; return { string: value }; } else if (type.typeRef) { const ref = type.typeRef.ref; const value = getTypeNameWithoutError(ref); if (value) { if (isPrimitiveGrammarType(value)) { return { primitive: value }; } else { return { value }; } } } } return { primitive: 'unknown' }; }