31
31
import org .eclipse .emf .ecore .resource .Resource ;
32
32
import org .eclipse .n4js .AnnotationDefinition ;
33
33
import org .eclipse .n4js .N4JSGlobals ;
34
+ import org .eclipse .n4js .n4JS .FormalParameter ;
34
35
import org .eclipse .n4js .n4JS .FunctionDefinition ;
35
36
import org .eclipse .n4js .n4JS .ImportSpecifier ;
37
+ import org .eclipse .n4js .n4JS .N4FieldDeclaration ;
36
38
import org .eclipse .n4js .n4JS .N4JSPackage ;
39
+ import org .eclipse .n4js .n4JS .N4MethodDeclaration ;
40
+ import org .eclipse .n4js .n4JS .N4TypeDeclaration ;
37
41
import org .eclipse .n4js .n4JS .NamedImportSpecifier ;
38
42
import org .eclipse .n4js .n4JS .NamespaceImportSpecifier ;
39
43
import org .eclipse .n4js .n4JS .TypeReferenceNode ;
66
70
import org .eclipse .n4js .ts .types .TField ;
67
71
import org .eclipse .n4js .ts .types .TFormalParameter ;
68
72
import org .eclipse .n4js .ts .types .TGetter ;
73
+ import org .eclipse .n4js .ts .types .TInterface ;
69
74
import org .eclipse .n4js .ts .types .TMember ;
70
75
import org .eclipse .n4js .ts .types .TMethod ;
71
76
import org .eclipse .n4js .ts .types .TModule ;
72
77
import org .eclipse .n4js .ts .types .TSetter ;
78
+ import org .eclipse .n4js .ts .types .TStructField ;
73
79
import org .eclipse .n4js .ts .types .TStructMember ;
74
- import org .eclipse .n4js .ts .types .TTypedElement ;
80
+ import org .eclipse .n4js .ts .types .TStructuralType ;
75
81
import org .eclipse .n4js .ts .types .Type ;
76
82
import org .eclipse .n4js .utils .N4JSLanguageUtils ;
77
83
import org .eclipse .n4js .utils .N4JSLanguageUtils .EnumKind ;
@@ -171,10 +177,10 @@ private void convertTypeRefNode(TypeReferenceNode_IM<?> typeRefNode) {
171
177
// special case: ArrayN in extends clause
172
178
String referenceStr = getReferenceToType (declType , getState ());
173
179
write (referenceStr );
174
- convertTypeArguments ((ParameterizedTypeRef ) typeRef );
180
+ convertTypeArguments (typeRefNode , (ParameterizedTypeRef ) typeRef );
175
181
} else {
176
182
// standard case
177
- convertTypeRef (typeRef );
183
+ convertTypeRef (typeRefNode , typeRef );
178
184
}
179
185
180
186
if (isReturnType ) {
@@ -188,15 +194,11 @@ private void convertTypeRefNode(TypeReferenceNode_IM<?> typeRefNode) {
188
194
}
189
195
}
190
196
191
- private void convertDeclaredTypeRef (TTypedElement elem ) {
192
- TypeRef declaredTypeRef = elem .getTypeRef ();
193
- if (declaredTypeRef != null ) {
194
- write (": " );
195
- convertTypeRef (declaredTypeRef );
196
- }
197
+ private void convertTypeRef (TypeRef typeRefRaw ) {
198
+ convertTypeRef (null , typeRefRaw );
197
199
}
198
200
199
- private void convertTypeRef (TypeRef typeRefRaw ) {
201
+ private void convertTypeRef (TypeReferenceNode_IM <?> typeRefNode , TypeRef typeRefRaw ) {
200
202
if (typeRefRaw == null ) {
201
203
return ;
202
204
}
@@ -217,7 +219,7 @@ private void convertTypeRef(TypeRef typeRefRaw) {
217
219
} else if (typeRef instanceof FunctionTypeExprOrRef ) {
218
220
convertFunctionTypeExprOrRef ((FunctionTypeExprOrRef ) typeRef );
219
221
} else if (typeRef instanceof ParameterizedTypeRef ) {
220
- convertParameterizedTypeRef ((ParameterizedTypeRef ) typeRef );
222
+ convertParameterizedTypeRef (typeRefNode , (ParameterizedTypeRef ) typeRef );
221
223
} else if (typeRef instanceof ThisTypeRef ) {
222
224
convertThisTypeRef ((ThisTypeRef ) typeRef );
223
225
} else if (typeRef instanceof ExistentialTypeRef ) {
@@ -278,15 +280,15 @@ private void convertFunctionTypeExprOrRef(FunctionTypeExprOrRef typeRef) {
278
280
}
279
281
}
280
282
281
- private void convertParameterizedTypeRef (ParameterizedTypeRef typeRef ) {
283
+ private void convertParameterizedTypeRef (TypeReferenceNode_IM <?> typeRefNode , ParameterizedTypeRef typeRef ) {
282
284
if (typeRef instanceof FunctionTypeRef ) {
283
285
convertFunctionTypeExprOrRef ((FunctionTypeRef ) typeRef );
284
286
return ;
285
287
}
286
288
Type declType = typeRef .getDeclaredType ();
287
289
288
290
if (isArrayN (getState ().G , declType )) {
289
- convertTypeArguments (typeRef , "[" , "]" );
291
+ convertTypeArguments (typeRefNode , typeRef , "[" , "]" );
290
292
return ;
291
293
}
292
294
@@ -302,11 +304,11 @@ private void convertParameterizedTypeRef(ParameterizedTypeRef typeRef) {
302
304
if (showDeclaredType ) {
303
305
String referenceStr = (declType == null ) ? null : getReferenceToType (declType , getState ());
304
306
if (referenceStr != null ) {
305
- String prependType = getStructuralTypeReplacements (typeRef );
307
+ String prependType = getStructuralTypeReplacements (typeRefNode , typeRef );
306
308
write (prependType );
307
309
308
310
write (referenceStr );
309
- convertTypeArguments (typeRef );
311
+ convertTypeArguments (typeRefNode , typeRef );
310
312
311
313
write (Strings .isNullOrEmpty (prependType ) ? "" : ">" );
312
314
@@ -321,7 +323,7 @@ private void convertParameterizedTypeRef(ParameterizedTypeRef typeRef) {
321
323
write (" & " );
322
324
}
323
325
write ("{" );
324
- write (members , m -> convertTMember (m ), "; " ); // ',' would also be allowed as separator
326
+ write (members , m -> convertTMember (typeRefNode , m ), "; " ); // ',' would also be allowed as separator
325
327
write ("}" );
326
328
}
327
329
@@ -331,7 +333,7 @@ private void convertParameterizedTypeRef(ParameterizedTypeRef typeRef) {
331
333
}
332
334
333
335
private void convertThisTypeRef (ThisTypeRef typeRef ) {
334
- String prependType = getStructuralTypeReplacements (typeRef );
336
+ String prependType = getStructuralTypeReplacements (null , typeRef );
335
337
write (prependType );
336
338
337
339
write ("this" );
@@ -361,7 +363,19 @@ private void convertLiteralTypeRef(LiteralTypeRef typeRef) {
361
363
}
362
364
}
363
365
364
- private String getStructuralTypeReplacements (TypeRef typeRef ) {
366
+ private String getStructuralTypeReplacements (TypeReferenceNode_IM <?> typeRefNode , TypeRef typeRef ) {
367
+ if (isCaseOfTypeScriptCircularityIssue (typeRefNode , typeRef )) {
368
+ switch (typeRef .getTypingStrategy ()) {
369
+ case STRUCTURAL_READ_ONLY_FIELDS :
370
+ case STRUCTURAL_FIELD_INITIALIZER :
371
+ return "Readonly<" ;
372
+ case STRUCTURAL_FIELDS :
373
+ case STRUCTURAL_WRITE_ONLY_FIELDS :
374
+ default :
375
+ return "" ;
376
+ }
377
+ }
378
+
365
379
switch (typeRef .getTypingStrategy ()) {
366
380
case STRUCTURAL_FIELDS :
367
381
return "StructuralFields<" ;
@@ -376,11 +390,79 @@ private String getStructuralTypeReplacements(TypeRef typeRef) {
376
390
}
377
391
}
378
392
379
- private void convertTypeArguments (ParameterizedTypeRef typeRef ) {
380
- convertTypeArguments (typeRef , "<" , ">" );
393
+ /**
394
+ * Mitigates TypeScript issue occurring on circular type references. Details see here:
395
+ * ReadonlyStructuralTypes_TS_circularity.n4js.xt
396
+ */
397
+ private boolean isCaseOfTypeScriptCircularityIssue (TypeReferenceNode_IM <?> typeRefNode , TypeRef typeRef ) {
398
+ if (typeRef instanceof ParameterizedTypeRefStructural
399
+ && typeRef .eContainer () instanceof ParameterizedTypeRefStructural ) {
400
+
401
+ EObject trTmp = typeRef ;
402
+ while (trTmp instanceof TypeRef ) {
403
+ trTmp = trTmp .eContainer ();
404
+ }
405
+ if (trTmp instanceof TStructField ) {
406
+ // case for fields type aliases
407
+ ParameterizedTypeRefStructural propTypeRef = (ParameterizedTypeRefStructural ) typeRef .eContainer ();
408
+ TStructuralType propType = propTypeRef .getStructuralType ();
409
+
410
+ if (propType == trTmp .eContainer ()) {
411
+ return true ;
412
+ }
413
+ }
414
+ if (trTmp instanceof TFormalParameter && trTmp .eContainer () != null ) {
415
+ // case for formal parameters in type aliases
416
+ ParameterizedTypeRefStructural paramTypeRef = (ParameterizedTypeRefStructural ) typeRef .eContainer ();
417
+ TStructuralType paramType = paramTypeRef .getStructuralType ();
418
+
419
+ if (paramType == trTmp .eContainer ().eContainer ()) {
420
+ return true ;
421
+ }
422
+ }
423
+ }
424
+
425
+ if (typeRefNode != null
426
+ && typeRefNode .eContainer () instanceof N4FieldDeclaration
427
+ && typeRefNode .eContainer ().eContainer () instanceof N4TypeDeclaration ) {
428
+
429
+ // case for interfaces and classes
430
+ Type referencedType = typeRef .getDeclaredType ();
431
+ N4TypeDeclaration containingTDecl = (N4TypeDeclaration ) typeRefNode .eContainer ().eContainer ();
432
+ Type containingType = getState ().info .getOriginalDefinedType (containingTDecl );
433
+
434
+ if (referencedType == containingType ) {
435
+ return true ;
436
+ }
437
+ }
438
+
439
+ if (typeRefNode != null
440
+ && typeRefNode .eContainer () instanceof FormalParameter
441
+ && typeRefNode .eContainer ().eContainer () instanceof N4MethodDeclaration
442
+ && typeRefNode .eContainer ().eContainer ().eContainer () instanceof N4TypeDeclaration ) {
443
+
444
+ // case for formal parameters
445
+ Type referencedType = typeRef .getDeclaredType ();
446
+ N4MethodDeclaration method = (N4MethodDeclaration ) typeRefNode .eContainer ().eContainer ();
447
+ N4TypeDeclaration containingTDecl = (N4TypeDeclaration ) typeRefNode .eContainer ().eContainer ().eContainer ();
448
+ Type containingType = getState ().info .getOriginalDefinedType (containingTDecl );
449
+
450
+ if (referencedType == containingType && !method .isConstructor ()) {
451
+ if (containingType instanceof TInterface ) {
452
+ return !method .isConstructSignature ();
453
+ }
454
+ return !method .isConstructor ();
455
+ }
456
+ }
457
+ return false ;
458
+ }
459
+
460
+ private void convertTypeArguments (TypeReferenceNode_IM <?> typeRefNode , ParameterizedTypeRef typeRef ) {
461
+ convertTypeArguments (typeRefNode , typeRef , "<" , ">" );
381
462
}
382
463
383
- private void convertTypeArguments (ParameterizedTypeRef typeRef , String prefix , String suffix ) {
464
+ private void convertTypeArguments (TypeReferenceNode_IM <?> typeRefNode , ParameterizedTypeRef typeRef , String prefix ,
465
+ String suffix ) {
384
466
List <TypeArgument > typeArgs = typeRef .getDeclaredTypeArgs ();
385
467
if (typeArgs .isEmpty ()) {
386
468
return ;
@@ -394,15 +476,15 @@ private void convertTypeArguments(ParameterizedTypeRef typeRef, String prefix, S
394
476
}
395
477
396
478
write (prefix );
397
- write (typeArgs , ta -> convertTypeArgument (ta ), ", " );
479
+ write (typeArgs , ta -> convertTypeArgument (typeRefNode , ta ), ", " );
398
480
write (suffix );
399
481
}
400
482
401
- private void convertTypeArgument (TypeArgument typeArg ) {
483
+ private void convertTypeArgument (TypeReferenceNode_IM <?> typeRefNode , TypeArgument typeArg ) {
402
484
if (typeArg instanceof Wildcard ) {
403
485
TypeRef upperBound = ((Wildcard ) typeArg ).getDeclaredOrImplicitUpperBound ();
404
486
if (upperBound != null ) {
405
- convertTypeArgument (upperBound );
487
+ convertTypeArgument (typeRefNode , upperBound );
406
488
} else {
407
489
write ("any" ); // TypeScript does not support lower bounds
408
490
}
@@ -421,7 +503,7 @@ private void convertTypeArgument(TypeArgument typeArg) {
421
503
// return;
422
504
}
423
505
424
- convertTypeRef (typeRef );
506
+ convertTypeRef (typeRefNode , typeRef );
425
507
}
426
508
427
509
private void convertTFormalParameters (Iterable <? extends TFormalParameter > fpars ) {
@@ -453,9 +535,9 @@ private void convertTFormalParameter(TFormalParameter fpar) {
453
535
}
454
536
}
455
537
456
- private void convertTMember (TMember member ) {
538
+ private void convertTMember (TypeReferenceNode_IM <?> typeRefNode , TMember member ) {
457
539
if (member instanceof TField ) {
458
- convertTMember ((TField ) member );
540
+ convertTMember (typeRefNode , (TField ) member );
459
541
} else if (member instanceof TGetter ) {
460
542
convertTMember ((TGetter ) member );
461
543
} else if (member instanceof TSetter ) {
@@ -468,12 +550,16 @@ private void convertTMember(TMember member) {
468
550
}
469
551
}
470
552
471
- private void convertTMember (TField field ) {
553
+ private void convertTMember (TypeReferenceNode_IM <?> typeRefNode , TField field ) {
472
554
writeQuotedIfNonIdentifier (field .getName ());
473
555
if (field .isOptional ()) {
474
556
write ("?" );
475
557
}
476
- convertDeclaredTypeRef (field );
558
+ TypeRef declaredTypeRef = field .getTypeRef ();
559
+ if (declaredTypeRef != null ) {
560
+ write (": " );
561
+ convertTypeRef (typeRefNode , declaredTypeRef );
562
+ }
477
563
}
478
564
479
565
private void convertTMember (TGetter getter ) {
0 commit comments