Skip to content

Commit 67f327b

Browse files
committed
[draft]
1 parent a19a793 commit 67f327b

File tree

10 files changed

+174
-19
lines changed

10 files changed

+174
-19
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// [test] arrayWithoutParam.kt
2+
@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS")
3+
4+
import kotlin.js.*
5+
import org.khronos.webgl.*
6+
import org.w3c.dom.*
7+
import org.w3c.dom.events.*
8+
import org.w3c.dom.parsing.*
9+
import org.w3c.dom.svg.*
10+
import org.w3c.dom.url.*
11+
import org.w3c.fetch.*
12+
import org.w3c.files.*
13+
import org.w3c.notifications.*
14+
import org.w3c.performance.*
15+
import org.w3c.workers.*
16+
import org.w3c.xhr.*
17+
18+
typealias Table = Array<Any>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare class Table extends Array {
2+
constructor();
3+
toString(): string;
4+
static version: string;
5+
}

typescript/ts-converter/src/AstConverter.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ export class AstConverter {
464464

465465
let symbol = this.typeChecker.getSymbolAtLocation(type.typeName);
466466
let typeReference: ReferenceEntity | null = null;
467-
let declaration = this.getFirstDeclaration(symbol);
467+
let declaration = this.getFirstDeclaration(symbol, params.length);
468468

469469
if (declaration) {
470470
if (ts.isTypeParameterDeclaration(declaration)) {
@@ -742,15 +742,18 @@ export class AstConverter {
742742
return this.astFactory.createQualifiedNameEntity(convertedExpression, name);
743743
}
744744

745-
private getFirstDeclaration(symbol: ts.Symbol | null): ts.Declaration | null {
745+
private getFirstDeclaration(symbol: ts.Symbol | null, typeParamsNum: number): ts.Declaration | null {
746746
if (symbol == null) {
747747
return null;
748748
}
749749

750750
if (Array.isArray(symbol.declarations)) {
751751
return symbol.declarations.find(decl => !ts.isModuleDeclaration(decl) &&
752-
!ts.isVariableDeclaration(decl) && !ts.isPropertyDeclaration(decl) && !ts.isPropertySignature(decl) &&
753-
!ts.isFunctionLike(decl))
752+
!ts.isPropertyDeclaration(decl) && !ts.isPropertySignature(decl) &&
753+
!ts.isFunctionLike(decl) && !(ts.isInterfaceDeclaration(decl) && decl.typeParameters && decl.typeParameters.filter(
754+
param => !param.default
755+
).length > typeParamsNum)
756+
)
754757
}
755758

756759
return null;
@@ -783,7 +786,7 @@ export class AstConverter {
783786
}
784787

785788
let symbol = this.typeChecker.getSymbolAtLocation(type.expression);
786-
let declaration = this.getFirstDeclaration(symbol);
789+
let declaration = this.getFirstDeclaration(symbol, typeArguments.length);
787790

788791
// class can implement itself, but in overwhelming majority of cases this was not the intention of the declaration author - see https://stackoverflow.com/questions/62418219/class-implementing-itself-instead-of-inheriting-an-eponymous-interface-in-outer
789792
if (declaration != parent) {

typescript/ts-converter/src/Dependency.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class TranslateSubsetOfSymbolsDependency implements Dependency {
4545
symbols.forEach(node => {
4646
let parent = node.parent;
4747
while (parent) {
48-
if (ts.isModuleDeclaration(parent)) {
48+
if (ts.isModuleDeclaration(parent) || ts.isVariableStatement(parent)) {
4949
parentUids.add(parent);
5050
}
5151
parent = parent.parent;
@@ -78,7 +78,7 @@ export class TranslateSubsetOfSymbolsDependency implements Dependency {
7878
return true;
7979
}
8080

81-
if (ts.isModuleDeclaration(node) && this.parentUids.has(node)) {
81+
if ((ts.isModuleDeclaration(node) || ts.isVariableStatement(node)) && this.parentUids.has(node)) {
8282
return true;
8383
}
8484

typescript/ts-converter/src/DependencyBuilder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class DependencyBuilder {
7171

7272
for (let declaration of declarations) {
7373
if (this.checkedReferences.has(declaration)) {
74-
return;
74+
continue;
7575
}
7676
this.checkedReferences.add(declaration);
7777
let sourceFile = declaration.getSourceFile();
@@ -103,7 +103,7 @@ export class DependencyBuilder {
103103
this.checkReferences(node.type)
104104
} else if (ts.isHeritageClause(node)) {
105105
for (let type of node.types) {
106-
this.checkReferences(type);
106+
this.checkReferences(type.expression);
107107
}
108108
} else if (ts.isExportDeclaration(node)) {
109109
if (node.exportClause) {

typescript/ts-converter/src/ExportContext.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function resolveName(node: ts.Node): string | null {
1414
return null;
1515
}
1616

17-
export function resolveDeclarations(node: ts.Identifier, typeChecker: ts.TypeChecker): Array<ts.Node> {
17+
export function resolveDeclarations(node: ts.Node, typeChecker: ts.TypeChecker): Array<ts.Node> {
1818
let symbolAtLocation = typeChecker.getSymbolAtLocation(node);
1919
if (symbolAtLocation) {
2020

typescript/ts-lowerings/src/org/jetbrains/dukat/tsLowerings/DeclarationLowering.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.jetbrains.dukat.ownerContext.wrap
77
import org.jetbrains.dukat.tsmodel.CallSignatureDeclaration
88
import org.jetbrains.dukat.tsmodel.ClassDeclaration
99
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
10+
import org.jetbrains.dukat.tsmodel.ConstructSignatureDeclaration
1011
import org.jetbrains.dukat.tsmodel.ConstructorDeclaration
1112
import org.jetbrains.dukat.tsmodel.Declaration
1213
import org.jetbrains.dukat.tsmodel.FunctionDeclaration
@@ -68,6 +69,16 @@ interface DeclarationLowering : TopLevelDeclarationLowering, DeclarationStatemen
6869
)
6970
}
7071

72+
fun lowerConstructSignatureDeclaration(declaration: ConstructSignatureDeclaration, owner: NodeOwner<MemberDeclaration>?): ConstructSignatureDeclaration {
73+
return declaration.copy(
74+
type = lowerParameterValue(declaration.type, owner.wrap(declaration)),
75+
parameters = declaration.parameters.map { parameter -> lowerParameterDeclaration(parameter, owner.wrap(declaration)) },
76+
typeParameters = declaration.typeParameters.map { typeParameter ->
77+
typeParameter.copy(constraints = typeParameter.constraints.map { constraint -> lowerParameterValue(constraint, owner.wrap(declaration)) })
78+
}
79+
)
80+
}
81+
7182
fun lowerIndexSignatureDeclaration(declaration: IndexSignatureDeclaration, owner: NodeOwner<MemberDeclaration>?): IndexSignatureDeclaration {
7283
return declaration.copy(
7384
parameters = declaration.parameters.map { indexType -> lowerParameterDeclaration(indexType, owner.wrap(declaration)) },
@@ -84,6 +95,7 @@ interface DeclarationLowering : TopLevelDeclarationLowering, DeclarationStatemen
8495
is MethodSignatureDeclaration -> lowerMethodSignatureDeclaration(declaration, newOwner)
8596
is MethodDeclaration -> lowerMethodDeclaration(declaration, newOwner)
8697
is CallSignatureDeclaration -> lowerCallSignatureDeclaration(declaration, newOwner)
98+
is ConstructSignatureDeclaration -> lowerConstructSignatureDeclaration(declaration, newOwner)
8799
is IndexSignatureDeclaration -> lowerIndexSignatureDeclaration(declaration, newOwner)
88100
else -> {
89101
logger.debug("[${this}] skipping ${declaration}")
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package org.jetbrains.dukat.tsLowerings
2+
3+
import org.jetbrains.dukat.astCommon.IdentifierEntity
4+
import org.jetbrains.dukat.ownerContext.NodeOwner
5+
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
6+
import org.jetbrains.dukat.tsmodel.ConstructSignatureDeclaration
7+
import org.jetbrains.dukat.tsmodel.HeritageClauseDeclaration
8+
import org.jetbrains.dukat.tsmodel.InterfaceDeclaration
9+
import org.jetbrains.dukat.tsmodel.ModuleDeclaration
10+
import org.jetbrains.dukat.tsmodel.ParameterOwnerDeclaration
11+
import org.jetbrains.dukat.tsmodel.SourceSetDeclaration
12+
import org.jetbrains.dukat.tsmodel.VariableDeclaration
13+
import org.jetbrains.dukat.tsmodel.types.ParameterValueDeclaration
14+
import org.jetbrains.dukat.tsmodel.types.TypeDeclaration
15+
16+
private class ReplaceTypesLowering(private val typesToReplace: Map<String, ParameterValueDeclaration>, private val depth: Int) : DeclarationLowering {
17+
private val newTypesToReplace = mutableMapOf<String, ParameterValueDeclaration>()
18+
19+
private fun findNewType(type: ParameterValueDeclaration): ParameterValueDeclaration? {
20+
if (type is TypeDeclaration && type.typeReference != null) {
21+
val uid = type.typeReference!!.uid
22+
if (typesToReplace.containsKey(uid)) {
23+
return typesToReplace.getValue(uid)
24+
}
25+
}
26+
return null
27+
}
28+
29+
override fun lowerParameterValue(
30+
declaration: ParameterValueDeclaration,
31+
owner: NodeOwner<ParameterOwnerDeclaration>?
32+
): ParameterValueDeclaration {
33+
return findNewType(declaration) ?: declaration
34+
}
35+
36+
override fun lowerHeritageClause(
37+
heritageClause: HeritageClauseDeclaration,
38+
owner: NodeOwner<ClassLikeDeclaration>?
39+
): HeritageClauseDeclaration {
40+
val reference = heritageClause.typeReference
41+
if (reference != null && typesToReplace.containsKey(reference.uid)) {
42+
val newType = typesToReplace.getValue(reference.uid)
43+
if (newType is TypeDeclaration) {
44+
return heritageClause.copy(name = newType.value, typeArguments = newType.params, typeReference = newType.typeReference)
45+
}
46+
}
47+
return heritageClause
48+
}
49+
50+
override fun lowerVariableDeclaration(declaration: VariableDeclaration, owner: NodeOwner<ModuleDeclaration>?): VariableDeclaration {
51+
val newType = findNewType(declaration.type)
52+
if (newType != null) {
53+
newTypesToReplace[declaration.uid] = newType
54+
return declaration.copy(type = newType)
55+
}
56+
return declaration
57+
}
58+
59+
override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
60+
val newSource = super.lower(source)
61+
return if (depth == 0) {
62+
ReplaceTypesLowering(newTypesToReplace, depth + 1).lower(newSource)
63+
} else {
64+
newSource
65+
}
66+
}
67+
}
68+
69+
private class ProcessConstructorInterfacesLowering : DeclarationLowering {
70+
71+
private val typesToReplace = mutableMapOf<String, ParameterValueDeclaration>()
72+
73+
private fun determineCommonReturnType(constructors: List<ConstructSignatureDeclaration>): ParameterValueDeclaration? {
74+
return constructors[0].type
75+
}
76+
77+
override fun lowerInterfaceDeclaration(
78+
declaration: InterfaceDeclaration,
79+
owner: NodeOwner<ModuleDeclaration>?
80+
): InterfaceDeclaration {
81+
val constructSignatures = declaration.members.filterIsInstance<ConstructSignatureDeclaration>()
82+
if (constructSignatures.isEmpty()) {
83+
return declaration
84+
}
85+
val commonReturnType = determineCommonReturnType(constructSignatures)
86+
if (commonReturnType is TypeDeclaration && commonReturnType.value == IdentifierEntity("Array")) {
87+
typesToReplace[declaration.uid] = commonReturnType
88+
}
89+
return declaration
90+
}
91+
92+
override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
93+
val newSource = super.lower(source)
94+
return ReplaceTypesLowering(typesToReplace, 0).lower(newSource)
95+
}
96+
}
97+
98+
class ProcessConstructorInterfaces : TsLowering {
99+
override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
100+
return ProcessConstructorInterfacesLowering().lower(source)
101+
}
102+
}

typescript/ts-lowerings/src/org/jetbrains/dukat/tsLowerings/desugarArrayDeclarations.kt

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@ package org.jetbrains.dukat.tsLowerings
22

33
import org.jetbrains.dukat.astCommon.IdentifierEntity
44
import org.jetbrains.dukat.ownerContext.NodeOwner
5+
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
6+
import org.jetbrains.dukat.tsmodel.InterfaceDeclaration
57
import org.jetbrains.dukat.tsmodel.ModuleDeclaration
68
import org.jetbrains.dukat.tsmodel.ParameterOwnerDeclaration
9+
import org.jetbrains.dukat.tsmodel.ReferenceDeclaration
710
import org.jetbrains.dukat.tsmodel.SourceFileDeclaration
811
import org.jetbrains.dukat.tsmodel.SourceSetDeclaration
12+
import org.jetbrains.dukat.tsmodel.TopLevelDeclaration
913
import org.jetbrains.dukat.tsmodel.types.TypeDeclaration
1014

11-
private class NativeArrayLowering : DeclarationLowering {
15+
private class NativeArrayLowering(private val arrayUid: String) : DeclarationLowering {
1216
override fun lowerTypeDeclaration(declaration: TypeDeclaration, owner: NodeOwner<ParameterOwnerDeclaration>?): TypeDeclaration {
1317
val declarationResolved = if (declaration.value == IdentifierEntity("@@ArraySugar")) {
14-
declaration.copy(value = IdentifierEntity("Array"))
18+
declaration.copy(value = IdentifierEntity("Array"), typeReference = ReferenceDeclaration(arrayUid))
1519
} else {
1620
declaration
1721
}
@@ -21,16 +25,25 @@ private class NativeArrayLowering : DeclarationLowering {
2125

2226
}
2327

24-
fun ModuleDeclaration.desugarArrayDeclarations(): ModuleDeclaration {
25-
return NativeArrayLowering().lowerSourceDeclaration(this, NodeOwner(this, null))
26-
}
28+
private class ArrayFinder : DeclarationLowering {
2729

28-
fun SourceFileDeclaration.desugarArrayDeclarations() = copy(root = root.desugarArrayDeclarations())
30+
var arrayUid: String? = null
2931

30-
fun SourceSetDeclaration.desugarArrayDeclarations() = copy(sources = sources.map(SourceFileDeclaration::desugarArrayDeclarations))
32+
override fun lowerInterfaceDeclaration(
33+
declaration: InterfaceDeclaration,
34+
owner: NodeOwner<ModuleDeclaration>?
35+
): InterfaceDeclaration {
36+
if (declaration.name == IdentifierEntity("Array") && arrayUid == null) {
37+
arrayUid = declaration.uid
38+
}
39+
return declaration
40+
}
41+
}
3142

3243
class DesugarArrayDeclarations(): TsLowering {
3344
override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
34-
return source.desugarArrayDeclarations()
45+
val arrayFinder = ArrayFinder()
46+
arrayFinder.lower(source)
47+
return NativeArrayLowering(arrayFinder.arrayUid ?: "UNKNOWN").lower(source)
3548
}
3649
}

typescript/ts-translator/src/org/jetbrains/dukat/ts/translator/TypescriptLowerer.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import org.jetbrains.dukat.tsLowerings.SpecifyUnionType
5757
import org.jetbrains.dukat.tsLowerings.lower
5858
import org.jetbrains.dukat.tsmodel.SourceSetDeclaration
5959
import org.jetbrains.dukat.nodeIntroduction.introduceModels
60+
import org.jetbrains.dukat.tsLowerings.ProcessConstructorInterfaces
6061
import org.jetbrains.dukat.tsLowerings.ProcessOptionalMethods
6162

6263
open class TypescriptLowerer(
@@ -70,6 +71,8 @@ open class TypescriptLowerer(
7071
IntroduceMissingConstructors(),
7172
AddPackageName(packageName),
7273
RemoveThisParameters(),
74+
DesugarArrayDeclarations(),
75+
ProcessConstructorInterfaces(),
7376
MergeModules(),
7477
MergeClassLikes(),
7578
IntroduceSyntheticExportModifiers(),
@@ -81,7 +84,6 @@ open class TypescriptLowerer(
8184
ConvertKeyOfsAndLookups(),
8285
LowerPrimitives(),
8386
GenerateInterfaceReferences(),
84-
DesugarArrayDeclarations(),
8587
FixImpossibleInheritance(),
8688
LowerPartialOf(),
8789
ResolveLoops(),

0 commit comments

Comments
 (0)