use of cz.habarta.typescript.generator.emitter.TsBeanModel in project typescript-generator by vojtechhabarta.
the class ModelCompiler method addImplementedProperties.
private TsModel addImplementedProperties(SymbolTable symbolTable, TsModel tsModel) {
final List<TsBeanModel> beans = new ArrayList<>();
for (TsBeanModel bean : tsModel.getBeans()) {
if (bean.isClass()) {
final List<TsPropertyModel> resultProperties = new ArrayList<>(bean.getProperties());
final Set<String> classPropertyNames = new LinkedHashSet<>();
for (TsPropertyModel property : bean.getProperties()) {
classPropertyNames.add(property.getName());
}
classPropertyNames.addAll(getInheritedProperties(symbolTable, tsModel, bean.getExtendsList()).keySet());
final List<TsPropertyModel> implementedProperties = getImplementedProperties(symbolTable, tsModel, bean.getImplementsList());
Collections.reverse(implementedProperties);
for (TsPropertyModel implementedProperty : implementedProperties) {
if (!classPropertyNames.contains(implementedProperty.getName())) {
resultProperties.add(0, implementedProperty);
classPropertyNames.add(implementedProperty.getName());
}
}
beans.add(bean.withProperties(resultProperties));
} else {
beans.add(bean);
}
}
return tsModel.withBeans(beans);
}
use of cz.habarta.typescript.generator.emitter.TsBeanModel in project typescript-generator by vojtechhabarta.
the class ModelCompiler method createAndUseTaggedUnions.
private TsModel createAndUseTaggedUnions(final SymbolTable symbolTable, TsModel tsModel) {
if (settings.disableTaggedUnions) {
return tsModel;
}
// create tagged unions
final List<TsBeanModel> beans = new ArrayList<>();
final LinkedHashSet<TsAliasModel> typeAliases = new LinkedHashSet<>(tsModel.getTypeAliases());
for (TsBeanModel bean : tsModel.getBeans()) {
if (!bean.getTaggedUnionClasses().isEmpty() && bean.getDiscriminantProperty() != null) {
final Symbol unionName = symbolTable.getSymbol(bean.getOrigin(), "Union");
final boolean isGeneric = !bean.getTypeParameters().isEmpty();
final List<TsType> unionTypes = new ArrayList<>();
for (Class<?> cls : bean.getTaggedUnionClasses()) {
final TsType type;
if (isGeneric && cls.getTypeParameters().length != 0) {
final List<String> mappedGenericVariables = GenericsResolver.mapGenericVariablesToBase(cls, bean.getOrigin());
type = new TsType.GenericReferenceType(symbolTable.getSymbol(cls), mappedGenericVariables.stream().map(TsType.GenericVariableType::new).collect(Collectors.toList()));
} else {
type = new TsType.ReferenceType(symbolTable.getSymbol(cls));
}
unionTypes.add(type);
}
final TsType.UnionType union = new TsType.UnionType(unionTypes);
final TsAliasModel tsAliasModel = new TsAliasModel(bean.getOrigin(), unionName, bean.getTypeParameters(), union, null);
beans.add(bean.withTaggedUnionAlias(tsAliasModel));
typeAliases.add(tsAliasModel);
} else {
beans.add(bean);
}
}
final TsModel modelWithTaggedUnions = tsModel.withBeans(beans).withTypeAliases(new ArrayList<>(typeAliases));
// use tagged unions
final TsModel modelWithUsedTaggedUnions = transformBeanPropertyTypes(modelWithTaggedUnions, new TsType.Transformer() {
@Override
public TsType transform(TsType.Context context, TsType tsType) {
final Class<?> cls = getOriginClass(symbolTable, tsType);
if (cls != null) {
final Symbol unionSymbol = symbolTable.hasSymbol(cls, "Union");
if (unionSymbol != null) {
if (tsType instanceof TsType.GenericReferenceType) {
final TsType.GenericReferenceType genericReferenceType = (TsType.GenericReferenceType) tsType;
return new TsType.GenericReferenceType(unionSymbol, genericReferenceType.typeArguments);
} else {
return new TsType.ReferenceType(unionSymbol);
}
}
}
return tsType;
}
});
return modelWithUsedTaggedUnions;
}
use of cz.habarta.typescript.generator.emitter.TsBeanModel in project typescript-generator by vojtechhabarta.
the class ModelCompiler method processBean.
private <T> TsBeanModel processBean(SymbolTable symbolTable, Model model, Map<Type, List<BeanModel>> children, BeanModel bean) {
final boolean isClass = mappedToClass(bean.getOrigin());
final List<TsType> extendsList = new ArrayList<>();
final List<TsType> implementsList = new ArrayList<>();
final TsType parentType = typeFromJava(symbolTable, bean.getParent());
if (parentType != null && !parentType.equals(TsType.Any)) {
final boolean isParentMappedToClass = mappedToClass(getOriginClass(symbolTable, parentType));
if (isClass && !isParentMappedToClass) {
implementsList.add(parentType);
} else {
extendsList.add(parentType);
}
}
final List<TsType> interfaces = new ArrayList<>();
for (Type aInterface : bean.getInterfaces()) {
final TsType interfaceType = typeFromJava(symbolTable, aInterface);
if (!interfaceType.equals(TsType.Any)) {
interfaces.add(interfaceType);
}
}
if (isClass) {
implementsList.addAll(interfaces);
} else {
extendsList.addAll(interfaces);
}
final List<TsPropertyModel> properties = processProperties(symbolTable, model, bean);
boolean isTaggedUnion = false;
if (bean.getDiscriminantProperty() != null && bean.getProperty(bean.getDiscriminantProperty()) == null) {
isTaggedUnion = true;
boolean isDisciminantProperty = true;
final List<BeanModel> selfAndDescendants = getSelfAndDescendants(bean, children);
final List<TsType.StringLiteralType> literals = new ArrayList<>();
for (BeanModel descendant : selfAndDescendants) {
if (descendant.getDiscriminantProperty() == null || descendant.getProperty(bean.getDiscriminantProperty()) != null) {
// do not handle bean as tagged union if any descendant or it itself has duplicate discriminant property
isTaggedUnion = false;
isDisciminantProperty = false;
}
if (descendant.getDiscriminantLiteral() != null) {
literals.add(new TsType.StringLiteralType(descendant.getDiscriminantLiteral()));
}
}
final List<BeanModel> descendants = selfAndDescendants.subList(1, selfAndDescendants.size());
for (BeanModel descendant : descendants) {
// do not handle bean as tagged union if any descendant has "non-related" generic parameter
final List<String> mappedGenericVariables = GenericsResolver.mapGenericVariablesToBase(descendant.getOrigin(), bean.getOrigin());
if (mappedGenericVariables.contains(null)) {
isTaggedUnion = false;
}
}
final TsType discriminantType = isDisciminantProperty && !literals.isEmpty() ? new TsType.UnionType(literals) : TsType.String;
final TsModifierFlags modifiers = TsModifierFlags.None.setReadonly(settings.declarePropertiesAsReadOnly);
properties.add(0, new TsPropertyModel(bean.getDiscriminantProperty(), discriminantType, modifiers, /*ownProperty*/
true, null));
}
final TsBeanModel tsBean = new TsBeanModel(bean.getOrigin(), TsBeanCategory.Data, isClass, symbolTable.getSymbol(bean.getOrigin()), getTypeParameters(bean.getOrigin()), parentType, extendsList, implementsList, properties, /*constructor*/
null, /*methods*/
null, bean.getComments());
return isTaggedUnion ? tsBean.withTaggedUnion(bean.getTaggedUnionClasses(), bean.getDiscriminantProperty(), bean.getDiscriminantLiteral()) : tsBean;
}
use of cz.habarta.typescript.generator.emitter.TsBeanModel in project typescript-generator by vojtechhabarta.
the class ModelCompiler method addConstructors.
private TsModel addConstructors(SymbolTable symbolTable, TsModel tsModel) {
final List<TsBeanModel> beans = new ArrayList<>();
for (TsBeanModel bean : tsModel.getBeans()) {
final Symbol beanIdentifier = symbolTable.getSymbol(bean.getOrigin());
final List<TsType.GenericVariableType> typeParameters = getTypeParameters(bean.getOrigin());
final TsType.ReferenceType dataType = typeParameters.isEmpty() ? new TsType.ReferenceType(beanIdentifier) : new TsType.GenericReferenceType(beanIdentifier, typeParameters);
final List<TsStatement> body = new ArrayList<>();
if (bean.getParent() != null) {
body.add(new TsExpressionStatement(new TsCallExpression(new TsSuperExpression(), new TsIdentifierReference("data"))));
}
for (TsPropertyModel property : bean.getProperties()) {
final Map<String, TsType> inheritedProperties = ModelCompiler.getInheritedProperties(symbolTable, tsModel, Utils.listFromNullable(bean.getParent()));
if (!inheritedProperties.containsKey(property.getName())) {
body.add(new TsExpressionStatement(new TsAssignmentExpression(new TsMemberExpression(new TsThisExpression(), property.name), new TsMemberExpression(new TsIdentifierReference("data"), property.name))));
}
}
if (bean.isClass()) {
final TsConstructorModel constructor = new TsConstructorModel(TsModifierFlags.None, Arrays.asList(new TsParameterModel("data", dataType)), body, /*comments*/
null);
beans.add(bean.withConstructor(constructor));
} else {
beans.add(bean);
}
}
return tsModel.withBeans(beans);
}
use of cz.habarta.typescript.generator.emitter.TsBeanModel in project typescript-generator by vojtechhabarta.
the class ModelCompiler method processModel.
private TsModel processModel(SymbolTable symbolTable, Model model) {
final Map<Type, List<BeanModel>> children = createChildrenMap(model);
final List<TsBeanModel> beans = new ArrayList<>();
for (BeanModel bean : model.getBeans()) {
beans.add(processBean(symbolTable, model, children, bean));
}
final List<TsEnumModel> enums = new ArrayList<>();
final List<TsEnumModel> stringEnums = new ArrayList<>();
for (EnumModel enumModel : model.getEnums()) {
final TsEnumModel tsEnumModel = processEnum(symbolTable, enumModel);
enums.add(tsEnumModel);
if (tsEnumModel.getKind() == EnumKind.StringBased) {
stringEnums.add(tsEnumModel);
}
}
return new TsModel().withBeans(beans).withEnums(enums).withOriginalStringEnums(stringEnums);
}
Aggregations