Skip to content
This repository was archived by the owner on Nov 6, 2019. It is now read-only.

Commit 9f22a05

Browse files
committed
Support abstract classes and abstract functions
1 parent 6d5ee9a commit 9f22a05

File tree

12 files changed

+55
-21
lines changed

12 files changed

+55
-21
lines changed

src/main/kotlin/ts2kt/TsClassToKt.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class TsClassToKt(
1515
isOverride: (MethodDeclaration) -> Boolean,
1616
isOverrideProperty: (PropertyDeclaration) -> Boolean,
1717
override val hasMembersOpenModifier: Boolean = true,
18-
override val needsNoImpl: Boolean = true
18+
override val needsNoImpl: Boolean = true,
19+
override val isAbstract: Boolean = false
1920
) : TsClassifierToKt(typeMapper, isOverride, isOverrideProperty) {
2021

2122
override val isInterface = false

src/main/kotlin/ts2kt/TsClassifierToKt.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ abstract class TsClassifierToKt(
7777
open fun isNullable(node: PropertyDeclaration): Boolean = false
7878
open fun isLambda(node: PropertyDeclaration): Boolean = false
7979

80-
open fun needsNoImpl(node: MethodDeclaration): Boolean = true
80+
open fun needsNoImpl(node: MethodDeclaration): Boolean = !isAbstract(node)
8181

8282
override fun visitPropertyDeclaration(node: PropertyDeclaration) {
8383
val declarationName = node.propertyName!!
@@ -100,7 +100,7 @@ abstract class TsClassifierToKt(
100100
open fun TsClassifierToKt.addFunction(name: String, isOverride: Boolean, needsNoImpl: Boolean, node: MethodDeclaration) {
101101
val symbol = typeMapper.typeChecker.getSymbolResolvingAliases(node)
102102
node.toKotlinCallSignatureOverloads(typeMapper).forEach { callSignature ->
103-
addFunction(symbol, name, callSignature, isOverride = isOverride, needsNoImpl = needsNoImpl(node))
103+
addFunction(symbol, name, callSignature, isOverride = isOverride, needsNoImpl = needsNoImpl(node), isAbstract = isAbstract(node))
104104
}
105105

106106
assert(node.body == null, "An function in declarations file should not have body, function '${this.name}.$name'")

src/main/kotlin/ts2kt/TsInterfaceToKt.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ open class TsInterfaceToKt(
1414

1515
override val hasMembersOpenModifier = false
1616

17+
override val isAbstract = false
18+
1719
override val needsNoImpl = false
1820

1921
override val isInterface: Boolean = true

src/main/kotlin/ts2kt/TsInterfaceToKtExtensions.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ class TsInterfaceToKtExtensions(
6161
needsNoImpl = true, additionalAnnotations = annotations, isOverride = isOverride)
6262
}
6363

64-
override fun addFunction(symbol: Symbol?, name: String, callSignature: KtCallSignature, extendsType: KtType?, needsNoImpl: Boolean, additionalAnnotations: List<KtAnnotation>, isOverride: Boolean, isOperator: Boolean) {
64+
override fun addFunction(symbol: Symbol?, name: String, callSignature: KtCallSignature, extendsType: KtType?, needsNoImpl: Boolean, additionalAnnotations: List<KtAnnotation>, isOverride: Boolean, isOperator: Boolean, isAbstract: Boolean) {
6565
val typeParamsWithoutClashes = this.typeParams.fixIfClashWith(callSignature.typeParams)
6666
val actualExtendsType = if (typeParamsWithoutClashes === this.typeParams) cachedExtendsType else getExtendsType(typeParamsWithoutClashes)
6767
val annotations = additionalAnnotations.withNativeAnnotation()
6868

69-
super.addFunction(symbol, name, KtCallSignature(callSignature.params, typeParamsWithoutClashes merge callSignature.typeParams, callSignature.returnType), actualExtendsType, true, annotations, isOverride, isOperator)
69+
super.addFunction(symbol, name, KtCallSignature(callSignature.params, typeParamsWithoutClashes merge callSignature.typeParams, callSignature.returnType), actualExtendsType, true, annotations, isOverride, isOperator, isAbstract)
7070
}
7171

7272
}

src/main/kotlin/ts2kt/TypeScriptToKotlin.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class TypeScriptToKotlin(
5555

5656
override val hasMembersOpenModifier = false
5757

58+
override val isAbstract = false
59+
5860
fun getAdditionalAnnotations(node: Node): List<KtAnnotation> {
5961
val isShouldSkip = requiredModifier === SyntaxKind.DeclareKeyword && !(node.modifiers?.arr?.any { it.kind === requiredModifier } ?: false )
6062
if (isShouldSkip) return DEFAULT_FAKE_ANNOTATION
@@ -125,7 +127,7 @@ class TypeScriptToKotlin(
125127
val name = node.propertyName?.asString()!!
126128
val symbol = node.name?.let { typeChecker.getSymbolResolvingAliases(it) }
127129
node.toKotlinCallSignatureOverloads(typeMapper).forEach { callSignature ->
128-
addFunction(symbol, name, callSignature, additionalAnnotations = additionalAnnotations)
130+
addFunction(symbol, name, callSignature, additionalAnnotations = additionalAnnotations, isAbstract = isAbstract(node))
129131
}
130132
processDefaultExport(node, symbol)
131133
}
@@ -151,7 +153,7 @@ class TypeScriptToKotlin(
151153
override fun visitClassDeclaration(node: ClassDeclaration) {
152154
val additionalAnnotations = getAdditionalAnnotations(node)
153155

154-
val translator = TsClassToKt(typeMapper, annotations = defaultAnnotations + additionalAnnotations, isOverride = isOverride, isOverrideProperty = isOverrideProperty)
156+
val translator = TsClassToKt(typeMapper, annotations = defaultAnnotations + additionalAnnotations, isOverride = isOverride, isOverrideProperty = isOverrideProperty, isAbstract = isAbstract(node))
155157
translator.visitClassDeclaration(node)
156158

157159
val result = translator.createClassifier()
@@ -181,7 +183,7 @@ class TypeScriptToKotlin(
181183

182184
val enumClass =
183185
KtClassifier(KtClassKind.ENUM, KtName(node.identifierName.unescapedText), listOf(), listOf(), listOf(),
184-
entries, listOf(), hasOpenModifier = false)
186+
entries, listOf(), hasOpenModifier = false, isAbstract = isAbstract(node))
185187

186188
val symbol = node.name?.let { typeChecker.getSymbolResolvingAliases(it) }
187189
addDeclaration(symbol, enumClass)

src/main/kotlin/ts2kt/TypeScriptToKotlinBase.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ package ts2kt
22

33
import ts2kt.kotlin.ast.*
44
import typescriptServices.ts.ImportEqualsDeclaration
5+
import typescriptServices.ts.Node
56
import typescriptServices.ts.Symbol
7+
import typescriptServices.ts.SyntaxKind
68

79
abstract class TypeScriptToKotlinBase(
810
val declarations: MutableList<KtMember>,
911
val declarationsBySymbol: MutableMap<Symbol, MutableList<KtMember>>
1012
) : Visitor {
1113
abstract val hasMembersOpenModifier: Boolean
1214
abstract val isInterface: Boolean
15+
abstract val isAbstract: Boolean
1316

1417
open val defaultAnnotations: List<KtAnnotation> = listOf()
1518

@@ -18,9 +21,9 @@ abstract class TypeScriptToKotlinBase(
1821
addDeclaration(symbol, KtVariable(KtName(name), KtTypeAnnotation(type), extendsType?.let { KtHeritageType(it) }, annotations, typeParams, isVar = isVar, needsNoImpl = needsNoImpl, isInInterface = isInterface, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier))
1922
}
2023

21-
open fun addFunction(symbol: Symbol?, name: String, callSignature: KtCallSignature, extendsType: KtType? = null, needsNoImpl: Boolean = true, additionalAnnotations: List<KtAnnotation> = listOf(), isOverride: Boolean = false, isOperator: Boolean = false) {
24+
open fun addFunction(symbol: Symbol?, name: String, callSignature: KtCallSignature, extendsType: KtType? = null, needsNoImpl: Boolean = true, additionalAnnotations: List<KtAnnotation> = listOf(), isOverride: Boolean = false, isOperator: Boolean = false, isAbstract: Boolean = false) {
2225
val annotations = defaultAnnotations + additionalAnnotations
23-
addDeclaration(symbol, KtFunction(KtName(name), callSignature, extendsType?.let { KtHeritageType(it) }, annotations, needsNoImpl = needsNoImpl, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier, isOperator = isOperator))
26+
addDeclaration(symbol, KtFunction(KtName(name), callSignature, extendsType?.let { KtHeritageType(it) }, annotations, needsNoImpl = needsNoImpl, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier && !isAbstract, isOperator = isOperator, isAbstract = isAbstract))
2427
}
2528

2629
protected fun addDeclaration(symbol: Symbol?, declaration: KtMember) {
@@ -31,6 +34,10 @@ abstract class TypeScriptToKotlinBase(
3134
}
3235
}
3336

37+
fun isAbstract(node: Node): Boolean {
38+
return node.modifiers?.arr?.any { it.kind == SyntaxKind.AbstractKeyword } == true
39+
}
40+
3441
// TODO
3542
open fun visitList(node: typescriptServices.ts.Node) {
3643
forEachChild(this, node)

src/main/kotlin/ts2kt/converterUtils.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import ts2kt.utils.reportUnsupportedNode
66
import typescriptServices.ts.*
77

88
fun TsInterfaceToKt.createClassifier() =
9-
KtClassifier(KtClassKind.INTERFACE, KtName(name!!), listOf(), typeParams, parents, declarations, annotations, hasOpenModifier = false)
9+
KtClassifier(KtClassKind.INTERFACE, KtName(name!!), listOf(), typeParams, parents, declarations, annotations, hasOpenModifier = false, isAbstract = false)
1010

1111
fun TsClassToKt.createClassifier(): KtClassifier? {
1212
if (name == null) return null
@@ -19,7 +19,7 @@ fun TsClassToKt.createClassifier(): KtClassifier? {
1919
}
2020
} ?: declarations
2121

22-
return KtClassifier(kind, KtName(name!!), paramsOfConstructors, typeParams, parents, members, annotations, hasOpenModifier = kind === ts2kt.kotlin.ast.KtClassKind.CLASS)
22+
return KtClassifier(kind, KtName(name!!), paramsOfConstructors, typeParams, parents, members, annotations, hasOpenModifier = kind === ts2kt.kotlin.ast.KtClassKind.CLASS && !isAbstract, isAbstract = isAbstract)
2323
}
2424

2525
val JS_MODULE = KtName("JsModule")

src/main/kotlin/ts2kt/kotlin/ast/Stringify.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private val EQ_NO_IMPL = " = $NO_IMPL"
1111
private val NO_IMPL_PROPERTY_GETTER = " get()" + EQ_NO_IMPL
1212
private val NO_IMPL_PROPERTY_SETTER = " set(value)" + EQ_NO_IMPL
1313
private val EXTERNAL = "external"
14+
private val ABSTRACT = "abstract"
1415
private val OPEN = "open"
1516
private val OVERRIDE = "override"
1617
private val OPERATOR = "operator"
@@ -78,10 +79,14 @@ class Stringify(
7879

7980
out.printIndent()
8081

82+
if (isAbstract) {
83+
out.print("$ABSTRACT ")
84+
}
85+
8186
printExternalIfNeed()
8287

8388
if (hasOpenModifier) {
84-
out.print(OPEN + " ")
89+
out.print("$OPEN ")
8590
}
8691

8792
out.print(kind.keyword)
@@ -134,6 +139,10 @@ class Stringify(
134139

135140
out.printIndent()
136141

142+
if (isAbstract) {
143+
out.print("$ABSTRACT ")
144+
}
145+
137146
// TODO remove hack
138147
printExternalIfNeed()
139148

@@ -159,7 +168,7 @@ class Stringify(
159168

160169
out.print(name.asString())
161170

162-
callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl, printDefaultValues = !isOverride)
171+
callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl || isAbstract, printDefaultValues = !isOverride)
163172

164173
if (needsNoImpl) {
165174
out.print(EQ_NO_IMPL)

src/main/kotlin/ts2kt/kotlin/ast/ast.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ data class KtClassifier(
119119
val parents: List<KtHeritageType>,
120120
override var members: List<KtMember>,
121121
override var annotations: List<KtAnnotation>,
122-
val hasOpenModifier: Boolean
122+
val hasOpenModifier: Boolean,
123+
val isAbstract: Boolean
123124
) : KtMember, AbstractKtNode(), KtWithMembers {
124125
override fun accept(visitor: KtVisitor) {
125126
visitor.visitClassifier(this)
@@ -155,7 +156,8 @@ data class KtFunction(
155156
val needsNoImpl: Boolean = true,
156157
val isOverride: Boolean = false,
157158
val hasOpenModifier: Boolean = false,
158-
val isOperator: Boolean = false
159+
val isOperator: Boolean = false,
160+
val isAbstract: Boolean = false
159161
) : KtMember, AbstractKtNode() {
160162
override fun accept(visitor: KtVisitor) {
161163
visitor.visitFunction(this)

src/main/kotlin/ts2kt/mergeDeclarations.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ private fun mergeClassAndInterface(klass: KtClassifier, iface: KtClassifier): Kt
9595
(klass.parents + iface.parents).distinct(),
9696
mutableListOf(),
9797
mutableListOf() /*annotations will be merged later*/,
98-
klass.hasOpenModifier /* TODO: should it be open? */
98+
klass.hasOpenModifier /* TODO: should it be open? */,
99+
klass.isAbstract
99100
)
100101

101102
return mergeClassifierMembers(result, klass, iface)
@@ -106,12 +107,12 @@ private fun mergeClassifierAndVariable(a: KtClassifier, b: KtVariable): KtMember
106107
assert(a.getClassObject() == null, "Unxpected `class object` when merge Classifier(kind=${a.kind}) and Variable(${b.stringify()})")
107108

108109
if (a.kind === KtClassKind.INTERFACE || a.isModule()) {
109-
val newTrait = KtClassifier(KtClassKind.INTERFACE, a.name, a.paramsOfConstructors, a.typeParams, a.parents, a.members, a.annotations, hasOpenModifier = false)
110+
val newTrait = KtClassifier(KtClassKind.INTERFACE, a.name, a.paramsOfConstructors, a.typeParams, a.parents, a.members, a.annotations, hasOpenModifier = false, isAbstract = false)
110111

111112
val delegation = listOf(KtHeritageType(b.type.type, byExpression = NO_IMPL))
112113

113114
// TODO drop hacks
114-
val classObject = KtClassifier(KtClassKind.COMPANION_OBJECT, KtName.NO_NAME, listOf(), listOf(), delegation, listOf(), listOf(), hasOpenModifier = false)
115+
val classObject = KtClassifier(KtClassKind.COMPANION_OBJECT, KtName.NO_NAME, listOf(), listOf(), delegation, listOf(), listOf(), hasOpenModifier = false, isAbstract = false)
115116

116117
newTrait.addMember(classObject)
117118

@@ -147,7 +148,7 @@ private fun mergeClassAndObject(a: KtClassifier, b: KtClassifier): KtClassifier
147148

148149
if (classObject == null) {
149150
// TODO drop hack
150-
a.addMember(KtClassifier(KtClassKind.COMPANION_OBJECT, KtName.NO_NAME, listOf(), listOf(), listOf(), b.members, NO_ANNOTATIONS, hasOpenModifier = false))
151+
a.addMember(KtClassifier(KtClassKind.COMPANION_OBJECT, KtName.NO_NAME, listOf(), listOf(), listOf(), b.members, NO_ANNOTATIONS, hasOpenModifier = false, isAbstract = false))
151152
}
152153
else {
153154
// TODO drop hack
@@ -191,7 +192,7 @@ fun KtPackagePartBuilder.mergeClassesAndPackages() {
191192
if (companion == null) {
192193
companion = KtClassifier(
193194
KtClassKind.COMPANION_OBJECT, KtName.NO_NAME, emptyList(), null, emptyList(),
194-
emptyList(), emptyList(), false)
195+
emptyList(), emptyList(), false, isAbstract = false)
195196
}
196197

197198
val (classifiers, nonClassifiers) = nestedPackage.members.partition { it is KtClassifier }

0 commit comments

Comments
 (0)