44import cz .habarta .typescript .generator .*;
55import cz .habarta .typescript .generator .emitter .*;
66import cz .habarta .typescript .generator .parser .*;
7+ import cz .habarta .typescript .generator .util .Utils ;
78import java .lang .reflect .*;
89import java .util .*;
910
@@ -41,6 +42,8 @@ public ModelCompiler(Settings settings, TypeProcessor typeProcessor) {
4142 public TsModel javaToTypeScript (Model model ) {
4243 final SymbolTable symbolTable = new SymbolTable (settings );
4344 TsModel tsModel = processModel (symbolTable , model );
45+ tsModel = removeInheritedProperties (symbolTable , tsModel );
46+ tsModel = addImplementedProperties (symbolTable , tsModel );
4447
4548 // dates
4649 tsModel = transformDates (symbolTable , tsModel );
@@ -59,6 +62,7 @@ public TsModel javaToTypeScript(Model model) {
5962 tsModel = createAndUseTaggedUnions (symbolTable , tsModel );
6063
6164 symbolTable .resolveSymbolNames ();
65+ tsModel = sortDeclarations (symbolTable , tsModel );
6266 return tsModel ;
6367 }
6468
@@ -86,7 +90,7 @@ private TsModel processModel(SymbolTable symbolTable, Model model) {
8690 private Map <Type , List <BeanModel >> createChildrenMap (Model model ) {
8791 final Map <Type , List <BeanModel >> children = new LinkedHashMap <>();
8892 for (BeanModel bean : model .getBeans ()) {
89- for (Type ancestor : bean .getDirectAncestors ()) {
93+ for (Type ancestor : bean .getParentAndInterfaces ()) {
9094 if (!children .containsKey (ancestor )) {
9195 children .put (ancestor , new ArrayList <BeanModel >());
9296 }
@@ -128,7 +132,8 @@ private TsBeanModel processBean(SymbolTable symbolTable, Map<Type, List<BeanMode
128132 properties .add (0 , new TsPropertyModel (bean .getDiscriminantProperty (), discriminantType , null ));
129133 }
130134
131- return new TsBeanModel (bean .getOrigin (), beanType , parentType , bean .getTaggedUnionClasses (), interfaces , properties , bean .getComments ());
135+ final boolean isClass = !bean .getOrigin ().isInterface () && settings .mapClasses == ClassMapping .asClasses ;
136+ return new TsBeanModel (bean .getOrigin (), isClass , beanType , parentType , bean .getTaggedUnionClasses (), interfaces , properties , bean .getComments ());
132137 }
133138
134139 private static List <BeanModel > getSelfAndDescendants (BeanModel bean , Map <Type , List <BeanModel >> children ) {
@@ -185,6 +190,76 @@ private TsType typeFromJava(SymbolTable symbolTable, Type javaType, String usedI
185190 }
186191 }
187192
193+ private TsModel removeInheritedProperties (SymbolTable symbolTable , TsModel tsModel ) {
194+ final List <TsBeanModel > beans = new ArrayList <>();
195+ for (TsBeanModel bean : tsModel .getBeans ()) {
196+ final Map <String , TsType > inheritedPropertyTypes = getInheritedProperties (symbolTable , tsModel , bean .getParentAndInterfaces ());
197+ final List <TsPropertyModel > properties = new ArrayList <>();
198+ for (TsPropertyModel property : bean .getProperties ()) {
199+ if (!Objects .equals (property .getTsType (), inheritedPropertyTypes .get (property .getName ()))) {
200+ properties .add (property );
201+ }
202+ }
203+ beans .add (bean .withProperties (properties ));
204+ }
205+ return tsModel .setBeans (beans );
206+ }
207+
208+ private TsModel addImplementedProperties (SymbolTable symbolTable , TsModel tsModel ) {
209+ final List <TsBeanModel > beans = new ArrayList <>();
210+ for (TsBeanModel bean : tsModel .getBeans ()) {
211+ if (bean .isClass ()) {
212+ final List <TsPropertyModel > resultProperties = new ArrayList <>(bean .getProperties ());
213+
214+ final Set <String > classPropertyNames = new LinkedHashSet <>();
215+ for (TsPropertyModel property : bean .getProperties ()) {
216+ classPropertyNames .add (property .getName ());
217+ }
218+ classPropertyNames .addAll (getInheritedProperties (symbolTable , tsModel , Utils .listFromNullable (bean .getParent ())).keySet ());
219+
220+ final List <TsPropertyModel > implementedProperties = getImplementedProperties (symbolTable , tsModel , bean .getInterfaces ());
221+ Collections .reverse (implementedProperties );
222+ for (TsPropertyModel implementedProperty : implementedProperties ) {
223+ if (!classPropertyNames .contains (implementedProperty .getName ())) {
224+ resultProperties .add (0 , implementedProperty );
225+ classPropertyNames .add (implementedProperty .getName ());
226+ }
227+ }
228+
229+ beans .add (bean .withProperties (resultProperties ));
230+ } else {
231+ beans .add (bean );
232+ }
233+ }
234+ return tsModel .setBeans (beans );
235+ }
236+
237+ private static Map <String , TsType > getInheritedProperties (SymbolTable symbolTable , TsModel tsModel , List <TsType > parents ) {
238+ final Map <String , TsType > properties = new LinkedHashMap <>();
239+ for (TsType parentType : parents ) {
240+ final TsBeanModel parent = tsModel .getBean (getOriginClass (symbolTable , parentType ));
241+ if (parent != null ) {
242+ properties .putAll (getInheritedProperties (symbolTable , tsModel , parent .getParentAndInterfaces ()));
243+ for (TsPropertyModel property : parent .getProperties ()) {
244+ properties .put (property .getName (), property .getTsType ());
245+ }
246+ }
247+ }
248+ return properties ;
249+ }
250+
251+ private static List <TsPropertyModel > getImplementedProperties (SymbolTable symbolTable , TsModel tsModel , List <TsType > interfaces ) {
252+ final List <TsPropertyModel > properties = new ArrayList <>();
253+ for (TsType aInterface : interfaces ) {
254+ final TsBeanModel bean = tsModel .getBean (getOriginClass (symbolTable , aInterface ));
255+ if (bean != null ) {
256+ properties .addAll (getImplementedProperties (symbolTable , tsModel , bean .getInterfaces ()));
257+ properties .addAll (bean .getProperties ());
258+ }
259+ }
260+ return properties ;
261+ }
262+
188263 private TsModel transformDates (SymbolTable symbolTable , TsModel tsModel ) {
189264 final TsAliasModel dateAsNumber = new TsAliasModel (new TsType .ReferenceType (symbolTable .getSyntheticSymbol ("DateAsNumber" )), TsType .Number , null );
190265 final TsAliasModel dateAsString = new TsAliasModel (new TsType .ReferenceType (symbolTable .getSyntheticSymbol ("DateAsString" )), TsType .String , null );
@@ -228,15 +303,10 @@ private TsModel inlineEnums(final TsModel tsModel, final SymbolTable symbolTable
228303 @ Override
229304 public TsType transform (TsType tsType ) {
230305 if (tsType instanceof TsType .EnumReferenceType ) {
231- final TsType .ReferenceType reference = (TsType .ReferenceType ) tsType ;
232- final Class <?> cls = symbolTable .getSymbolClass (reference .symbol );
233- if (cls != null ) {
234- for (TsAliasModel alias : tsModel .getTypeAliases ()) {
235- if (alias .getOrigin () == cls ) {
236- inlinedAliases .add (alias );
237- return alias .getDefinition ();
238- }
239- }
306+ final TsAliasModel alias = tsModel .getTypeAlias (getOriginClass (symbolTable , tsType ));
307+ if (alias != null ) {
308+ inlinedAliases .add (alias );
309+ return alias .getDefinition ();
240310 }
241311 }
242312 return tsType ;
@@ -271,14 +341,11 @@ private TsModel createAndUseTaggedUnions(final SymbolTable symbolTable, TsModel
271341 final TsModel model = transformBeanPropertyTypes (tsModel , new TsType .Transformer () {
272342 @ Override
273343 public TsType transform (TsType tsType ) {
274- if (tsType instanceof TsType .ReferenceType ) {
275- final TsType .ReferenceType referenceType = (TsType .ReferenceType ) tsType ;
276- if (!(referenceType instanceof TsType .GenericReferenceType )) {
277- final Class <?> cls = symbolTable .getSymbolClass (referenceType .symbol );
278- final Symbol unionSymbol = symbolTable .hasSymbol (cls , "Union" );
279- if (unionSymbol != null ) {
280- return new TsType .ReferenceType (unionSymbol );
281- }
344+ final Class <?> cls = getOriginClass (symbolTable , tsType );
345+ if (cls != null && !(tsType instanceof TsType .GenericReferenceType )) {
346+ final Symbol unionSymbol = symbolTable .hasSymbol (cls , "Union" );
347+ if (unionSymbol != null ) {
348+ return new TsType .ReferenceType (unionSymbol );
282349 }
283350 }
284351 return tsType ;
@@ -287,6 +354,42 @@ public TsType transform(TsType tsType) {
287354 return model .setTypeAliases (new ArrayList <>(typeAliases ));
288355 }
289356
357+ private TsModel sortDeclarations (SymbolTable symbolTable , TsModel tsModel ) {
358+ final List <TsBeanModel > beans = tsModel .getBeans ();
359+ final List <TsAliasModel > aliases = tsModel .getTypeAliases ();
360+ final List <TsEnumModel <?>> enums = tsModel .getEnums ();
361+ if (settings .sortDeclarations ) {
362+ for (TsBeanModel bean : beans ) {
363+ Collections .sort (bean .getProperties ());
364+ }
365+ }
366+ if (settings .sortDeclarations || settings .sortTypeDeclarations ) {
367+ Collections .sort (beans );
368+ Collections .sort (aliases );
369+ Collections .sort (enums );
370+ }
371+ final LinkedHashSet <TsBeanModel > orderedBeans = new LinkedHashSet <>();
372+ for (TsBeanModel bean : beans ) {
373+ addOrderedClass (symbolTable , tsModel , bean , orderedBeans );
374+ }
375+ return tsModel
376+ .setBeans (new ArrayList <>(orderedBeans ))
377+ .setTypeAliases (aliases )
378+ .setEnums (enums );
379+ }
380+
381+ private static void addOrderedClass (SymbolTable symbolTable , TsModel tsModel , TsBeanModel bean , LinkedHashSet <TsBeanModel > orderedBeans ) {
382+ // for classes first add their parents to ordered list
383+ if (bean .isClass () && bean .getParent () != null ) {
384+ final TsBeanModel parentBean = tsModel .getBean (getOriginClass (symbolTable , bean .getParent ()));
385+ if (parentBean != null ) {
386+ addOrderedClass (symbolTable , tsModel , parentBean , orderedBeans );
387+ }
388+ }
389+ // add current bean to the ordered list
390+ orderedBeans .add (bean );
391+ }
392+
290393 private static TsModel transformBeanPropertyTypes (TsModel tsModel , TsType .Transformer transformer ) {
291394 final List <TsBeanModel > newBeans = new ArrayList <>();
292395 for (TsBeanModel bean : tsModel .getBeans ()) {
@@ -300,4 +403,12 @@ private static TsModel transformBeanPropertyTypes(TsModel tsModel, TsType.Transf
300403 return tsModel .setBeans (newBeans );
301404 }
302405
406+ private static Class <?> getOriginClass (SymbolTable symbolTable , TsType type ) {
407+ if (type instanceof TsType .ReferenceType ) {
408+ final TsType .ReferenceType referenceType = (TsType .ReferenceType ) type ;
409+ return symbolTable .getSymbolClass (referenceType .symbol );
410+ }
411+ return null ;
412+ }
413+
303414}
0 commit comments