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

Commit 400d23d

Browse files
committed
Support abstract classes and abstract functions
1 parent 16ef64d commit 400d23d

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
@@ -81,7 +81,7 @@ abstract class TsClassifierToKt(
8181
open fun isNullable(node: PropertyDeclaration): Boolean = false
8282
open fun isLambda(node: PropertyDeclaration): Boolean = false
8383

84-
open fun needsNoImpl(node: MethodDeclaration): Boolean = true
84+
open fun needsNoImpl(node: MethodDeclaration): Boolean = !isAbstract(node)
8585

8686
override fun visitPropertyDeclaration(node: PropertyDeclaration) {
8787
val declarationName = node.propertyName!!
@@ -104,7 +104,7 @@ abstract class TsClassifierToKt(
104104
open fun TsClassifierToKt.addFunction(name: String, isOverride: Boolean, needsNoImpl: Boolean, node: MethodDeclaration) {
105105
val symbol = typeMapper.typeChecker.getSymbolResolvingAliases(node)
106106
node.toKotlinCallSignatureOverloads(typeMapper).forEach { callSignature ->
107-
addFunction(symbol, name, callSignature, isOverride = isOverride, needsNoImpl = needsNoImpl(node))
107+
addFunction(symbol, name, callSignature, isOverride = isOverride, needsNoImpl = needsNoImpl(node), isAbstract = isAbstract(node))
108108
}
109109

110110
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
@@ -66,12 +66,12 @@ class TsInterfaceToKtExtensions(
6666
needsNoImpl = true, additionalAnnotations = annotations, isOverride = isOverride)
6767
}
6868

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

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

7777
}

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 || it.kind === SyntaxKind.ExportKeyword } ?: 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
@@ -13,6 +13,7 @@ private val EQ_NO_IMPL = " = $NO_IMPL"
1313
private val NO_IMPL_PROPERTY_GETTER = " get()" + EQ_NO_IMPL
1414
private val NO_IMPL_PROPERTY_SETTER = " set(value)" + EQ_NO_IMPL
1515
private val EXTERNAL = "external"
16+
private val ABSTRACT = "abstract"
1617
private val INLINE = "inline"
1718
private val OPEN = "open"
1819
private val OVERRIDE = "override"
@@ -81,10 +82,14 @@ class Stringify(
8182

8283
out.printIndent()
8384

85+
if (isAbstract) {
86+
out.print("$ABSTRACT ")
87+
}
88+
8489
printExternalIfNeed()
8590

8691
if (hasOpenModifier) {
87-
out.print(OPEN + " ")
92+
out.print("$OPEN ")
8893
}
8994

9095
out.print(kind.keyword)
@@ -137,6 +142,10 @@ class Stringify(
137142

138143
out.printIndent()
139144

145+
if (isAbstract) {
146+
out.print("$ABSTRACT ")
147+
}
148+
140149
if (function.extendsType == null) {
141150
// TODO remove hack
142151
printExternalIfNeed()
@@ -168,7 +177,7 @@ class Stringify(
168177

169178
out.print(name.asString())
170179

171-
callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl, printDefaultValues = !isOverride, noImpl = extendsType == null)
180+
callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl || isAbstract, printDefaultValues = !isOverride, noImpl = extendsType == null)
172181

173182
if (function.extendsType != null) {
174183
out.print(" { " )

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ data class KtClassifier(
123123
val parents: List<KtHeritageType>,
124124
override var members: List<KtMember>,
125125
override var annotations: List<KtAnnotation>,
126-
val hasOpenModifier: Boolean
126+
val hasOpenModifier: Boolean,
127+
val isAbstract: Boolean
127128
) : KtMember, AbstractKtNode(), KtWithMembers {
128129
override fun accept(visitor: KtVisitor) {
129130
visitor.visitClassifier(this)
@@ -159,7 +160,8 @@ data class KtFunction(
159160
val needsNoImpl: Boolean = true,
160161
val isOverride: Boolean = false,
161162
val hasOpenModifier: Boolean = false,
162-
val isOperator: Boolean = false
163+
val isOperator: Boolean = false,
164+
val isAbstract: Boolean = false
163165
) : KtMember, KtExtensionAware, AbstractKtNode() {
164166
override fun accept(visitor: KtVisitor) {
165167
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)