Skip to content

Commit

Permalink
[draft]
Browse files Browse the repository at this point in the history
  • Loading branch information
trilis committed Sep 7, 2020
1 parent a19a793 commit 67f327b
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 19 deletions.
18 changes: 18 additions & 0 deletions compiler/test/data/typescript/stdlib/arrayWithoutParam.d.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// [test] arrayWithoutParam.kt
@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS")

import kotlin.js.*
import org.khronos.webgl.*
import org.w3c.dom.*
import org.w3c.dom.events.*
import org.w3c.dom.parsing.*
import org.w3c.dom.svg.*
import org.w3c.dom.url.*
import org.w3c.fetch.*
import org.w3c.files.*
import org.w3c.notifications.*
import org.w3c.performance.*
import org.w3c.workers.*
import org.w3c.xhr.*

typealias Table = Array<Any>
5 changes: 5 additions & 0 deletions compiler/test/data/typescript/stdlib/arrayWithoutParam.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare class Table extends Array {
constructor();
toString(): string;
static version: string;
}
13 changes: 8 additions & 5 deletions typescript/ts-converter/src/AstConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ export class AstConverter {

let symbol = this.typeChecker.getSymbolAtLocation(type.typeName);
let typeReference: ReferenceEntity | null = null;
let declaration = this.getFirstDeclaration(symbol);
let declaration = this.getFirstDeclaration(symbol, params.length);

if (declaration) {
if (ts.isTypeParameterDeclaration(declaration)) {
Expand Down Expand Up @@ -742,15 +742,18 @@ export class AstConverter {
return this.astFactory.createQualifiedNameEntity(convertedExpression, name);
}

private getFirstDeclaration(symbol: ts.Symbol | null): ts.Declaration | null {
private getFirstDeclaration(symbol: ts.Symbol | null, typeParamsNum: number): ts.Declaration | null {
if (symbol == null) {
return null;
}

if (Array.isArray(symbol.declarations)) {
return symbol.declarations.find(decl => !ts.isModuleDeclaration(decl) &&
!ts.isVariableDeclaration(decl) && !ts.isPropertyDeclaration(decl) && !ts.isPropertySignature(decl) &&
!ts.isFunctionLike(decl))
!ts.isPropertyDeclaration(decl) && !ts.isPropertySignature(decl) &&
!ts.isFunctionLike(decl) && !(ts.isInterfaceDeclaration(decl) && decl.typeParameters && decl.typeParameters.filter(
param => !param.default
).length > typeParamsNum)
)
}

return null;
Expand Down Expand Up @@ -783,7 +786,7 @@ export class AstConverter {
}

let symbol = this.typeChecker.getSymbolAtLocation(type.expression);
let declaration = this.getFirstDeclaration(symbol);
let declaration = this.getFirstDeclaration(symbol, typeArguments.length);

// 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
if (declaration != parent) {
Expand Down
4 changes: 2 additions & 2 deletions typescript/ts-converter/src/Dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class TranslateSubsetOfSymbolsDependency implements Dependency {
symbols.forEach(node => {
let parent = node.parent;
while (parent) {
if (ts.isModuleDeclaration(parent)) {
if (ts.isModuleDeclaration(parent) || ts.isVariableStatement(parent)) {
parentUids.add(parent);
}
parent = parent.parent;
Expand Down Expand Up @@ -78,7 +78,7 @@ export class TranslateSubsetOfSymbolsDependency implements Dependency {
return true;
}

if (ts.isModuleDeclaration(node) && this.parentUids.has(node)) {
if ((ts.isModuleDeclaration(node) || ts.isVariableStatement(node)) && this.parentUids.has(node)) {
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions typescript/ts-converter/src/DependencyBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class DependencyBuilder {

for (let declaration of declarations) {
if (this.checkedReferences.has(declaration)) {
return;
continue;
}
this.checkedReferences.add(declaration);
let sourceFile = declaration.getSourceFile();
Expand Down Expand Up @@ -103,7 +103,7 @@ export class DependencyBuilder {
this.checkReferences(node.type)
} else if (ts.isHeritageClause(node)) {
for (let type of node.types) {
this.checkReferences(type);
this.checkReferences(type.expression);
}
} else if (ts.isExportDeclaration(node)) {
if (node.exportClause) {
Expand Down
2 changes: 1 addition & 1 deletion typescript/ts-converter/src/ExportContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function resolveName(node: ts.Node): string | null {
return null;
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.jetbrains.dukat.ownerContext.wrap
import org.jetbrains.dukat.tsmodel.CallSignatureDeclaration
import org.jetbrains.dukat.tsmodel.ClassDeclaration
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
import org.jetbrains.dukat.tsmodel.ConstructSignatureDeclaration
import org.jetbrains.dukat.tsmodel.ConstructorDeclaration
import org.jetbrains.dukat.tsmodel.Declaration
import org.jetbrains.dukat.tsmodel.FunctionDeclaration
Expand Down Expand Up @@ -68,6 +69,16 @@ interface DeclarationLowering : TopLevelDeclarationLowering, DeclarationStatemen
)
}

fun lowerConstructSignatureDeclaration(declaration: ConstructSignatureDeclaration, owner: NodeOwner<MemberDeclaration>?): ConstructSignatureDeclaration {
return declaration.copy(
type = lowerParameterValue(declaration.type, owner.wrap(declaration)),
parameters = declaration.parameters.map { parameter -> lowerParameterDeclaration(parameter, owner.wrap(declaration)) },
typeParameters = declaration.typeParameters.map { typeParameter ->
typeParameter.copy(constraints = typeParameter.constraints.map { constraint -> lowerParameterValue(constraint, owner.wrap(declaration)) })
}
)
}

fun lowerIndexSignatureDeclaration(declaration: IndexSignatureDeclaration, owner: NodeOwner<MemberDeclaration>?): IndexSignatureDeclaration {
return declaration.copy(
parameters = declaration.parameters.map { indexType -> lowerParameterDeclaration(indexType, owner.wrap(declaration)) },
Expand All @@ -84,6 +95,7 @@ interface DeclarationLowering : TopLevelDeclarationLowering, DeclarationStatemen
is MethodSignatureDeclaration -> lowerMethodSignatureDeclaration(declaration, newOwner)
is MethodDeclaration -> lowerMethodDeclaration(declaration, newOwner)
is CallSignatureDeclaration -> lowerCallSignatureDeclaration(declaration, newOwner)
is ConstructSignatureDeclaration -> lowerConstructSignatureDeclaration(declaration, newOwner)
is IndexSignatureDeclaration -> lowerIndexSignatureDeclaration(declaration, newOwner)
else -> {
logger.debug("[${this}] skipping ${declaration}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.jetbrains.dukat.tsLowerings

import org.jetbrains.dukat.astCommon.IdentifierEntity
import org.jetbrains.dukat.ownerContext.NodeOwner
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
import org.jetbrains.dukat.tsmodel.ConstructSignatureDeclaration
import org.jetbrains.dukat.tsmodel.HeritageClauseDeclaration
import org.jetbrains.dukat.tsmodel.InterfaceDeclaration
import org.jetbrains.dukat.tsmodel.ModuleDeclaration
import org.jetbrains.dukat.tsmodel.ParameterOwnerDeclaration
import org.jetbrains.dukat.tsmodel.SourceSetDeclaration
import org.jetbrains.dukat.tsmodel.VariableDeclaration
import org.jetbrains.dukat.tsmodel.types.ParameterValueDeclaration
import org.jetbrains.dukat.tsmodel.types.TypeDeclaration

private class ReplaceTypesLowering(private val typesToReplace: Map<String, ParameterValueDeclaration>, private val depth: Int) : DeclarationLowering {
private val newTypesToReplace = mutableMapOf<String, ParameterValueDeclaration>()

private fun findNewType(type: ParameterValueDeclaration): ParameterValueDeclaration? {
if (type is TypeDeclaration && type.typeReference != null) {
val uid = type.typeReference!!.uid
if (typesToReplace.containsKey(uid)) {
return typesToReplace.getValue(uid)
}
}
return null
}

override fun lowerParameterValue(
declaration: ParameterValueDeclaration,
owner: NodeOwner<ParameterOwnerDeclaration>?
): ParameterValueDeclaration {
return findNewType(declaration) ?: declaration
}

override fun lowerHeritageClause(
heritageClause: HeritageClauseDeclaration,
owner: NodeOwner<ClassLikeDeclaration>?
): HeritageClauseDeclaration {
val reference = heritageClause.typeReference
if (reference != null && typesToReplace.containsKey(reference.uid)) {
val newType = typesToReplace.getValue(reference.uid)
if (newType is TypeDeclaration) {
return heritageClause.copy(name = newType.value, typeArguments = newType.params, typeReference = newType.typeReference)
}
}
return heritageClause
}

override fun lowerVariableDeclaration(declaration: VariableDeclaration, owner: NodeOwner<ModuleDeclaration>?): VariableDeclaration {
val newType = findNewType(declaration.type)
if (newType != null) {
newTypesToReplace[declaration.uid] = newType
return declaration.copy(type = newType)
}
return declaration
}

override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
val newSource = super.lower(source)
return if (depth == 0) {
ReplaceTypesLowering(newTypesToReplace, depth + 1).lower(newSource)
} else {
newSource
}
}
}

private class ProcessConstructorInterfacesLowering : DeclarationLowering {

private val typesToReplace = mutableMapOf<String, ParameterValueDeclaration>()

private fun determineCommonReturnType(constructors: List<ConstructSignatureDeclaration>): ParameterValueDeclaration? {
return constructors[0].type
}

override fun lowerInterfaceDeclaration(
declaration: InterfaceDeclaration,
owner: NodeOwner<ModuleDeclaration>?
): InterfaceDeclaration {
val constructSignatures = declaration.members.filterIsInstance<ConstructSignatureDeclaration>()
if (constructSignatures.isEmpty()) {
return declaration
}
val commonReturnType = determineCommonReturnType(constructSignatures)
if (commonReturnType is TypeDeclaration && commonReturnType.value == IdentifierEntity("Array")) {
typesToReplace[declaration.uid] = commonReturnType
}
return declaration
}

override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
val newSource = super.lower(source)
return ReplaceTypesLowering(typesToReplace, 0).lower(newSource)
}
}

class ProcessConstructorInterfaces : TsLowering {
override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
return ProcessConstructorInterfacesLowering().lower(source)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ package org.jetbrains.dukat.tsLowerings

import org.jetbrains.dukat.astCommon.IdentifierEntity
import org.jetbrains.dukat.ownerContext.NodeOwner
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
import org.jetbrains.dukat.tsmodel.InterfaceDeclaration
import org.jetbrains.dukat.tsmodel.ModuleDeclaration
import org.jetbrains.dukat.tsmodel.ParameterOwnerDeclaration
import org.jetbrains.dukat.tsmodel.ReferenceDeclaration
import org.jetbrains.dukat.tsmodel.SourceFileDeclaration
import org.jetbrains.dukat.tsmodel.SourceSetDeclaration
import org.jetbrains.dukat.tsmodel.TopLevelDeclaration
import org.jetbrains.dukat.tsmodel.types.TypeDeclaration

private class NativeArrayLowering : DeclarationLowering {
private class NativeArrayLowering(private val arrayUid: String) : DeclarationLowering {
override fun lowerTypeDeclaration(declaration: TypeDeclaration, owner: NodeOwner<ParameterOwnerDeclaration>?): TypeDeclaration {
val declarationResolved = if (declaration.value == IdentifierEntity("@@ArraySugar")) {
declaration.copy(value = IdentifierEntity("Array"))
declaration.copy(value = IdentifierEntity("Array"), typeReference = ReferenceDeclaration(arrayUid))
} else {
declaration
}
Expand All @@ -21,16 +25,25 @@ private class NativeArrayLowering : DeclarationLowering {

}

fun ModuleDeclaration.desugarArrayDeclarations(): ModuleDeclaration {
return NativeArrayLowering().lowerSourceDeclaration(this, NodeOwner(this, null))
}
private class ArrayFinder : DeclarationLowering {

fun SourceFileDeclaration.desugarArrayDeclarations() = copy(root = root.desugarArrayDeclarations())
var arrayUid: String? = null

fun SourceSetDeclaration.desugarArrayDeclarations() = copy(sources = sources.map(SourceFileDeclaration::desugarArrayDeclarations))
override fun lowerInterfaceDeclaration(
declaration: InterfaceDeclaration,
owner: NodeOwner<ModuleDeclaration>?
): InterfaceDeclaration {
if (declaration.name == IdentifierEntity("Array") && arrayUid == null) {
arrayUid = declaration.uid
}
return declaration
}
}

class DesugarArrayDeclarations(): TsLowering {
override fun lower(source: SourceSetDeclaration): SourceSetDeclaration {
return source.desugarArrayDeclarations()
val arrayFinder = ArrayFinder()
arrayFinder.lower(source)
return NativeArrayLowering(arrayFinder.arrayUid ?: "UNKNOWN").lower(source)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import org.jetbrains.dukat.tsLowerings.SpecifyUnionType
import org.jetbrains.dukat.tsLowerings.lower
import org.jetbrains.dukat.tsmodel.SourceSetDeclaration
import org.jetbrains.dukat.nodeIntroduction.introduceModels
import org.jetbrains.dukat.tsLowerings.ProcessConstructorInterfaces
import org.jetbrains.dukat.tsLowerings.ProcessOptionalMethods

open class TypescriptLowerer(
Expand All @@ -70,6 +71,8 @@ open class TypescriptLowerer(
IntroduceMissingConstructors(),
AddPackageName(packageName),
RemoveThisParameters(),
DesugarArrayDeclarations(),
ProcessConstructorInterfaces(),
MergeModules(),
MergeClassLikes(),
IntroduceSyntheticExportModifiers(),
Expand All @@ -81,7 +84,6 @@ open class TypescriptLowerer(
ConvertKeyOfsAndLookups(),
LowerPrimitives(),
GenerateInterfaceReferences(),
DesugarArrayDeclarations(),
FixImpossibleInheritance(),
LowerPartialOf(),
ResolveLoops(),
Expand Down

0 comments on commit 67f327b

Please sign in to comment.