Skip to content
This repository was archived by the owner on Nov 6, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/kotlin/ts2kt/TsClassToKt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class TsClassToKt(
isOverride: (MethodDeclaration) -> Boolean,
isOverrideProperty: (PropertyDeclaration) -> Boolean,
override val hasMembersOpenModifier: Boolean = true,
override val needsNoImpl: Boolean = true
override val needsNoImpl: Boolean = true,
override val isAbstract: Boolean = false
) : TsClassifierToKt(typeMapper, isOverride, isOverrideProperty) {

override val isInterface = false
Expand Down
13 changes: 8 additions & 5 deletions src/main/kotlin/ts2kt/TsClassifierToKt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ abstract class TsClassifierToKt(
return this
}

open fun needsNoImpl(node: PropertyDeclaration): Boolean = true
open fun needsNoImpl(node: PropertyDeclaration): Boolean = !isAbstract(node)
open fun isNullable(node: PropertyDeclaration): Boolean = false
open fun isLambda(node: PropertyDeclaration): Boolean = false

open fun needsNoImpl(node: MethodDeclaration): Boolean = true
open fun needsNoImpl(node: MethodDeclaration): Boolean = !isAbstract(node)

override fun visitPropertyDeclaration(node: PropertyDeclaration) {
val declarationName = node.propertyName!!
Expand All @@ -97,14 +97,17 @@ abstract class TsClassifierToKt(
name,
type = varType.copy(isNullable = varType.isNullable || isNullable(node)),
isOverride = isOverride,
needsNoImpl = needsNoImpl(node)
isVar = !isReadonly(node),
isAbstract = isAbstract(node),
needsNoImpl = needsNoImpl(node),
accessModifier = getAccessModifier(node)
)
}

open fun TsClassifierToKt.addFunction(name: String, isOverride: Boolean, needsNoImpl: Boolean, node: MethodDeclaration) {
val symbol = typeMapper.typeChecker.getSymbolResolvingAliases(node)
node.toKotlinCallSignatureOverloads(typeMapper).forEach { callSignature ->
addFunction(symbol, name, callSignature, isOverride = isOverride, needsNoImpl = needsNoImpl(node))
addFunction(symbol, name, callSignature, isOverride = isOverride, needsNoImpl = needsNoImpl(node), isAbstract = isAbstract(node), accessModifier = getAccessModifier(node))
}

assert(node.body == null, "An function in declarations file should not have body, function '${this.name}.$name'")
Expand All @@ -121,7 +124,7 @@ abstract class TsClassifierToKt(

override fun visitSignatureDeclaration(node: SignatureDeclaration) {
node.toKotlinCallSignatureOverloads(typeMapper).forEach { callSignature ->
addFunction(null, INVOKE, callSignature, needsNoImpl = false, additionalAnnotations = listOf(NATIVE_INVOKE_ANNOTATION), isOperator = true)
addFunction(null, INVOKE, callSignature, needsNoImpl = false, additionalAnnotations = listOf(NATIVE_INVOKE_ANNOTATION), isOperator = true, accessModifier = getAccessModifier(node))
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/main/kotlin/ts2kt/TsInterfaceToKt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ open class TsInterfaceToKt(

override val hasMembersOpenModifier = false

override val isAbstract = false

override val needsNoImpl = false

override val isInterface: Boolean = true
Expand All @@ -28,12 +30,13 @@ open class TsInterfaceToKt(
override fun TsClassifierToKt.addFunction(name: String, isOverride: Boolean, needsNoImpl: Boolean, node: MethodDeclaration) {
val isOptional = node.questionToken != null
val symbol = typeMapper.typeChecker.getSymbolResolvingAliases(node)
val accessModifier = getAccessModifier(node)
if (isOptional) {
val call = node.toKotlinCallSignature(typeMapper)
addVariable(symbol, name, type = createFunctionType(call.params, call.returnType.type).copy(isNullable = true), typeParams = call.typeParams, isVar = false, needsNoImpl = true, isOverride = isOverride)
addVariable(symbol, name, type = createFunctionType(call.params, call.returnType.type).copy(isNullable = true), typeParams = call.typeParams, isVar = false, needsNoImpl = true, isOverride = isOverride, accessModifier = accessModifier)
} else {
node.toKotlinCallSignatureOverloads(typeMapper).forEach { call ->
addFunction(symbol, name, call, needsNoImpl = false, isOverride = isOverride)
addFunction(symbol, name, call, needsNoImpl = false, isOverride = isOverride, accessModifier = accessModifier)
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/main/kotlin/ts2kt/TsInterfaceToKtExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,22 @@ class TsInterfaceToKtExtensions(
super.translateGetterAndSetter(node, extendsType = cachedExtendsType)
}

override fun addVariable(symbol: Symbol?, name: String, type: KtType, extendsType: KtType?, typeParams: List<KtTypeParam>?, isVar: Boolean, needsNoImpl: Boolean, additionalAnnotations: List<KtAnnotation>, isOverride: Boolean) {
override fun addVariable(symbol: Symbol?, name: String, type: KtType, extendsType: KtType?, typeParams: List<KtTypeParam>?, isVar: Boolean, isAbstract: Boolean, needsNoImpl: Boolean, additionalAnnotations: List<KtAnnotation>, isOverride: Boolean, accessModifier: AccessModifier) {
val typeParamsWithoutClashes = this.typeParams.fixIfClashWith(typeParams)
val actualExtendsType = if (typeParamsWithoutClashes === this.typeParams) cachedExtendsType else getExtendsType(typeParamsWithoutClashes)
val annotations = additionalAnnotations.withNativeAnnotation()

super.addVariable(symbol, name, type, actualExtendsType, typeParamsWithoutClashes merge typeParams, isVar,
needsNoImpl = true, additionalAnnotations = annotations, isOverride = isOverride)
needsNoImpl = !isAbstract, additionalAnnotations = annotations, isOverride = isOverride, isAbstract = isAbstract,
accessModifier = accessModifier)
}

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

super.addFunction(symbol, name, KtCallSignature(callSignature.params, typeParamsWithoutClashes merge callSignature.typeParams, callSignature.returnType), actualExtendsType, true, annotations, isOverride, isOperator)
super.addFunction(symbol, name, KtCallSignature(callSignature.params, typeParamsWithoutClashes merge callSignature.typeParams, callSignature.returnType), actualExtendsType, true, annotations, isOverride, isOperator, isAbstract, accessModifier)
}

}
10 changes: 6 additions & 4 deletions src/main/kotlin/ts2kt/TypeScriptToKotlin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class TypeScriptToKotlin(

override val hasMembersOpenModifier = false

override val isAbstract = false

fun getAdditionalAnnotations(node: Node): List<KtAnnotation> {
val isShouldSkip = requiredModifier === SyntaxKind.DeclareKeyword && !(node.modifiers?.arr?.any { it.kind === requiredModifier || it.kind === SyntaxKind.ExportKeyword } ?: false )
if (isShouldSkip) return DEFAULT_FAKE_ANNOTATION
Expand Down Expand Up @@ -94,7 +96,7 @@ class TypeScriptToKotlin(
}
}
val varType = d.type?.let { typeMapper.mapType(it) } ?: KtType(ANY)
addVariable(symbol, name, varType, additionalAnnotations = additionalAnnotations)
addVariable(symbol, name, varType, additionalAnnotations = additionalAnnotations, accessModifier = getAccessModifier(node))
}
}

Expand Down Expand Up @@ -125,7 +127,7 @@ class TypeScriptToKotlin(
val name = node.propertyName?.asString()!!
val symbol = node.name?.let { typeChecker.getSymbolResolvingAliases(it) }
node.toKotlinCallSignatureOverloads(typeMapper).forEach { callSignature ->
addFunction(symbol, name, callSignature, additionalAnnotations = additionalAnnotations)
addFunction(symbol, name, callSignature, additionalAnnotations = additionalAnnotations, isAbstract = isAbstract(node))
}
processDefaultExport(node, symbol)
}
Expand All @@ -151,7 +153,7 @@ class TypeScriptToKotlin(
override fun visitClassDeclaration(node: ClassDeclaration) {
val additionalAnnotations = getAdditionalAnnotations(node)

val translator = TsClassToKt(typeMapper, annotations = defaultAnnotations + additionalAnnotations, isOverride = isOverride, isOverrideProperty = isOverrideProperty)
val translator = TsClassToKt(typeMapper, annotations = defaultAnnotations + additionalAnnotations, isOverride = isOverride, isOverrideProperty = isOverrideProperty, isAbstract = isAbstract(node))
translator.visitClassDeclaration(node)

val result = translator.createClassifier()
Expand Down Expand Up @@ -181,7 +183,7 @@ class TypeScriptToKotlin(

val enumClass =
KtClassifier(KtClassKind.ENUM, KtName(node.identifierName.unescapedText), listOf(), listOf(), listOf(),
entries, listOf(), hasOpenModifier = false)
entries, listOf(), hasOpenModifier = false, isAbstract = isAbstract(node))

val symbol = node.name?.let { typeChecker.getSymbolResolvingAliases(it) }
addDeclaration(symbol, enumClass)
Expand Down
37 changes: 29 additions & 8 deletions src/main/kotlin/ts2kt/TypeScriptToKotlinBase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,53 @@ package ts2kt

import ts2kt.kotlin.ast.*
import typescriptServices.ts.ImportEqualsDeclaration
import typescriptServices.ts.Node
import typescriptServices.ts.Symbol
import typescriptServices.ts.SyntaxKind

abstract class TypeScriptToKotlinBase(
val declarations: MutableList<KtMember>,
val declarationsBySymbol: MutableMap<Symbol, MutableList<KtMember>>
) : Visitor {
abstract val hasMembersOpenModifier: Boolean
abstract val isInterface: Boolean
abstract val isAbstract: Boolean

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

open fun addVariable(symbol: Symbol?, name: String, type: KtType, extendsType: KtType? = null, typeParams: List<KtTypeParam>? = null, isVar: Boolean = true, needsNoImpl: Boolean = true, additionalAnnotations: List<KtAnnotation> = listOf(), isOverride: Boolean = false) {
open fun addVariable(symbol: Symbol?, name: String, type: KtType, extendsType: KtType? = null, typeParams: List<KtTypeParam>? = null, isVar: Boolean = true, isAbstract: Boolean = false, needsNoImpl: Boolean = !isAbstract, additionalAnnotations: List<KtAnnotation> = listOf(), isOverride: Boolean = false, accessModifier: AccessModifier = AccessModifier.PUBLIC) {
val annotations = defaultAnnotations + additionalAnnotations
addDeclaration(symbol, KtVariable(KtName(name), KtTypeAnnotation(type), extendsType?.let { KtHeritageType(it) }, annotations, typeParams, isVar = isVar, needsNoImpl = needsNoImpl, isInInterface = isInterface, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier))
addDeclaration(symbol, KtVariable(KtName(name), KtTypeAnnotation(type), extendsType?.let { KtHeritageType(it) }, annotations, typeParams, isVar = isVar, needsNoImpl = needsNoImpl, isInInterface = isInterface, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier && !isAbstract, isAbstract = isAbstract, accessModifier = accessModifier))
}

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) {
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, accessModifier: AccessModifier = AccessModifier.PUBLIC) {
val annotations = defaultAnnotations + additionalAnnotations
addDeclaration(symbol, KtFunction(KtName(name), callSignature, extendsType?.let { KtHeritageType(it) }, annotations, needsNoImpl = needsNoImpl, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier, isOperator = isOperator))
addDeclaration(symbol, KtFunction(KtName(name), callSignature, extendsType?.let { KtHeritageType(it) }, annotations, needsNoImpl = needsNoImpl, isOverride = isOverride, hasOpenModifier = hasMembersOpenModifier && !isAbstract, isOperator = isOperator, isAbstract = isAbstract, accessModifier = accessModifier))
}

protected fun addDeclaration(symbol: Symbol?, declaration: KtMember) {
declarations += declaration
if (symbol != null) {
val values = declarationsBySymbol.getOrPut(symbol) { mutableListOf() }
values += declaration
if (declaration.accessModifier.usable) {
declarations += declaration
if (symbol != null) {
val values = declarationsBySymbol.getOrPut(symbol) { mutableListOf() }
values += declaration
}
}
}

fun isAbstract(node: Node): Boolean {
return node.modifiers?.arr?.any { it.kind == SyntaxKind.AbstractKeyword } == true
}

fun isReadonly(node: Node): Boolean {
return node.modifiers?.arr?.any { it.kind == SyntaxKind.ReadonlyKeyword } == true
}

fun getAccessModifier(node: Node): AccessModifier {
return when {
node.modifiers?.arr?.any { it.kind == SyntaxKind.ProtectedKeyword } == true -> AccessModifier.PROTECTED
node.modifiers?.arr?.any { it.kind == SyntaxKind.PrivateKeyword } == true -> AccessModifier.PRIVATE
else -> AccessModifier.PUBLIC
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/ts2kt/converterUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ts2kt.utils.reportUnsupportedNode
import typescriptServices.ts.*

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

fun TsClassToKt.createClassifier(): KtClassifier? {
if (name == null) return null
Expand All @@ -19,7 +19,7 @@ fun TsClassToKt.createClassifier(): KtClassifier? {
}
} ?: declarations

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

val JS_MODULE = KtName("JsModule")
Expand Down
26 changes: 24 additions & 2 deletions src/main/kotlin/ts2kt/kotlin/ast/Stringify.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ private val EQ_NO_IMPL = " = $NO_IMPL"
private val NO_IMPL_PROPERTY_GETTER = " get()" + EQ_NO_IMPL
private val NO_IMPL_PROPERTY_SETTER = " set(value)" + EQ_NO_IMPL
private val EXTERNAL = "external"
private val PROTECTED = "protected"
private val ABSTRACT = "abstract"
private val INLINE = "inline"
private val OPEN = "open"
private val OVERRIDE = "override"
Expand Down Expand Up @@ -81,10 +83,14 @@ class Stringify(

out.printIndent()

if (isAbstract) {
out.print("$ABSTRACT ")
}

printExternalIfNeed()

if (hasOpenModifier) {
out.print(OPEN + " ")
out.print("$OPEN ")
}

out.print(kind.keyword)
Expand Down Expand Up @@ -137,6 +143,14 @@ class Stringify(

out.printIndent()

if (accessModifier == AccessModifier.PROTECTED) {
out.print("$PROTECTED ")
}

if (isAbstract) {
out.print("$ABSTRACT ")
}

if (function.extendsType == null) {
// TODO remove hack
printExternalIfNeed()
Expand Down Expand Up @@ -168,7 +182,7 @@ class Stringify(

out.print(name.asString())

callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl, printDefaultValues = !isOverride, noImpl = extendsType == null)
callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl || isAbstract, printDefaultValues = !isOverride, noImpl = extendsType == null)

if (function.extendsType != null) {
out.print(" { " )
Expand All @@ -193,6 +207,14 @@ class Stringify(

out.printIndent()

if (accessModifier == AccessModifier.PROTECTED) {
out.print("$PROTECTED ")
}

if (isAbstract) {
out.print("$ABSTRACT ")
}

if (variable.extendsType == null) {
// TODO remove hack
printExternalIfNeed()
Expand Down
26 changes: 21 additions & 5 deletions src/main/kotlin/ts2kt/kotlin/ast/ast.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ interface KtAnnotated {
var annotations: List<KtAnnotation>
}

interface KtMember : KtNode, KtNamed, KtAnnotated
interface KtMember : KtNode, KtNamed, KtAnnotated {
val accessModifier: AccessModifier
}

interface KtExtensionAware : KtMember {
val extendsType: KtHeritageType?
Expand Down Expand Up @@ -123,8 +125,12 @@ data class KtClassifier(
val parents: List<KtHeritageType>,
override var members: List<KtMember>,
override var annotations: List<KtAnnotation>,
val hasOpenModifier: Boolean
val hasOpenModifier: Boolean,
val isAbstract: Boolean
) : KtMember, AbstractKtNode(), KtWithMembers {

override val accessModifier: AccessModifier = AccessModifier.PUBLIC

override fun accept(visitor: KtVisitor) {
visitor.visitClassifier(this)
}
Expand Down Expand Up @@ -159,7 +165,9 @@ data class KtFunction(
val needsNoImpl: Boolean = true,
val isOverride: Boolean = false,
val hasOpenModifier: Boolean = false,
val isOperator: Boolean = false
val isOperator: Boolean = false,
val isAbstract: Boolean = false,
override val accessModifier: AccessModifier = AccessModifier.PUBLIC
) : KtMember, KtExtensionAware, AbstractKtNode() {
override fun accept(visitor: KtVisitor) {
visitor.visitFunction(this)
Expand All @@ -173,17 +181,21 @@ data class KtVariable(
override var annotations: List<KtAnnotation>,
val typeParams: List<KtTypeParam>?,
var isVar: Boolean,
val needsNoImpl: Boolean = true,
val isAbstract: Boolean = false,
val needsNoImpl: Boolean = !isAbstract,
val isInInterface: Boolean,
val isOverride: Boolean = false,
val hasOpenModifier: Boolean
val hasOpenModifier: Boolean,
override val accessModifier: AccessModifier = AccessModifier.PUBLIC
) : KtMember, KtExtensionAware, AbstractKtNode() {
override fun accept(visitor: KtVisitor) {
visitor.visitVariable(this)
}
}

data class KtEnumEntry(override var name: KtName, val value: String? = null) : KtMember, AbstractKtNode() {
override val accessModifier: AccessModifier = AccessModifier.PUBLIC

override var annotations = listOf<KtAnnotation>()

override fun accept(visitor: KtVisitor) {
Expand Down Expand Up @@ -248,3 +260,7 @@ data class KtTypeAnnotation(var type: KtType, val isVararg: Boolean = false) : A
visitor.visitTypeAnnotation(this)
}
}

enum class AccessModifier(val usable: Boolean) {
PUBLIC(true), PROTECTED(true), INTERNAL(false), PRIVATE(false)
}
Loading