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

Commit b4f50fe

Browse files
epabstSchahen
authored andcommitted
Don't specify external for extension functions and variables (#121)
* Don't specify external for extension functions and variables This fixes #109 * Remove @file:JsQualifier if all functions & variables are extensions This fixes a compilation error that external functions and variables can't be in a file annotated with @file:JsQualifier.
1 parent 0ce8da5 commit b4f50fe

File tree

8 files changed

+87
-48
lines changed

8 files changed

+87
-48
lines changed

src/main/kotlin/converter/KtPackagePartBuilder.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ package converter
22

33
import ts2kt.JS_MODULE
44
import ts2kt.JS_QUALIFIER
5-
import ts2kt.kotlin.ast.KtAnnotation
6-
import ts2kt.kotlin.ast.KtArgument
7-
import ts2kt.kotlin.ast.KtMember
8-
import ts2kt.kotlin.ast.KtPackagePart
5+
import ts2kt.kotlin.ast.*
96
import ts2kt.moduleAnnotation
107
import typescriptServices.ts.Symbol
118

@@ -24,7 +21,7 @@ class KtPackagePartBuilder(
2421
fun build(): KtPackagePart {
2522
val allAnnotations = annotations.toMutableList()
2623

27-
if (members.none { it.annotations.any { it.name == JS_MODULE } }) {
24+
if (members.none { it.annotations.any { it.name == JS_MODULE } } && members.all { it !is KtExtensionAware || it.extendsType == null }) {
2825
getEnclosingModule()?.let {
2926
allAnnotations += moduleAnnotation(it)
3027
}

src/main/kotlin/ts2kt/TsClassifierToKt.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ abstract class TsClassifierToKt(
2121
}
2222

2323
override fun visitIndexSignature(node: IndexSignatureDeclaration) {
24-
translateAccessor(node, isGetter = true)
25-
translateAccessor(node, isGetter = false)
24+
translateGetterAndSetter(node, extendsType = null)
2625
}
2726

28-
private fun translateAccessor(node: IndexSignatureDeclaration, isGetter: Boolean) {
27+
protected fun translateGetterAndSetter(node: IndexSignatureDeclaration, extendsType: KtType?) {
28+
translateAccessor(node, isGetter = true, extendsType = extendsType)
29+
translateAccessor(node, isGetter = false, extendsType = extendsType)
30+
}
31+
32+
private fun translateAccessor(node: IndexSignatureDeclaration, isGetter: Boolean, extendsType: KtType?) {
2933
// TODO type params?
3034
node.parameters.toKotlinParamsOverloads(typeMapper).forEach { params ->
3135
val propTypeUnion = if (isGetter) {
@@ -36,20 +40,20 @@ abstract class TsClassifierToKt(
3640
propTypeUnion.possibleTypes.forEach { propType ->
3741
val callSignature: KtCallSignature
3842
val accessorName: String
39-
val annotation: KtAnnotation
43+
val annotation: KtAnnotation?
4044
if (isGetter) {
4145
// per Kotlin, all @nativeGetter's must be nullable
4246
callSignature = KtCallSignature(params, listOf(), KtTypeAnnotation(propType.copy(isNullable = true)))
4347
accessorName = GET
44-
annotation = NATIVE_GETTER_ANNOTATION
48+
annotation = if (extendsType == null) NATIVE_GETTER_ANNOTATION else null
4549
}
4650
else {
4751
callSignature = KtCallSignature(listOf(params[0], KtFunParam(KtName("value"), KtTypeAnnotation(propType))), listOf(), KtTypeAnnotation(KtType(UNIT)))
4852
accessorName = SET
49-
annotation = NATIVE_SETTER_ANNOTATION
53+
annotation = if (extendsType == null) NATIVE_SETTER_ANNOTATION else null
5054
}
5155

52-
addFunction(null, accessorName, callSignature, needsNoImpl = needsNoImpl, additionalAnnotations = listOf(annotation), isOperator = true)
56+
addFunction(null, accessorName, callSignature, needsNoImpl = needsNoImpl, additionalAnnotations = listOf(annotation).filterNotNull(), isOperator = true)
5357
}
5458
}
5559
}

src/main/kotlin/ts2kt/TsInterfaceToKtExtensions.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ts2kt
22

33
import ts2kt.kotlin.ast.*
44
import ts2kt.utils.assert
5+
import typescriptServices.ts.IndexSignatureDeclaration
56
import typescriptServices.ts.MethodDeclaration
67
import typescriptServices.ts.PropertyDeclaration
78
import typescriptServices.ts.Symbol
@@ -52,6 +53,10 @@ class TsInterfaceToKtExtensions(
5253
}
5354
}
5455

56+
override fun visitIndexSignature(node: IndexSignatureDeclaration) {
57+
super.translateGetterAndSetter(node, extendsType = cachedExtendsType)
58+
}
59+
5560
override fun addVariable(symbol: Symbol?, name: String, type: KtType, extendsType: KtType?, typeParams: List<KtTypeParam>?, isVar: Boolean, needsNoImpl: Boolean, additionalAnnotations: List<KtAnnotation>, isOverride: Boolean) {
5661
val typeParamsWithoutClashes = this.typeParams.fixIfClashWith(typeParams)
5762
val actualExtendsType = if (typeParamsWithoutClashes === this.typeParams) cachedExtendsType else getExtendsType(typeParamsWithoutClashes)

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

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package ts2kt.kotlin.ast
22

33
import ts2kt.DYNAMIC
44
import ts2kt.NATIVE_ANNOTATION
5+
import ts2kt.NATIVE_INVOKE_ANNOTATION
6+
import ts2kt.UNIT
57
import ts2kt.escapeIfNeed
68
import ts2kt.sanitize
79

@@ -11,6 +13,7 @@ private val EQ_NO_IMPL = " = $NO_IMPL"
1113
private val NO_IMPL_PROPERTY_GETTER = " get()" + EQ_NO_IMPL
1214
private val NO_IMPL_PROPERTY_SETTER = " set(value)" + EQ_NO_IMPL
1315
private val EXTERNAL = "external"
16+
private val INLINE = "inline"
1417
private val OPEN = "open"
1518
private val OVERRIDE = "override"
1619
private val OPERATOR = "operator"
@@ -130,12 +133,14 @@ class Stringify(
130133

131134
override fun visitFunction(function: KtFunction) {
132135
with(function) {
133-
annotations.acceptForEach(this@Stringify)
136+
annotations.filter { function.extendsType == null || it != NATIVE_INVOKE_ANNOTATION }.acceptForEach(this@Stringify)
134137

135138
out.printIndent()
136139

137-
// TODO remove hack
138-
printExternalIfNeed()
140+
if (function.extendsType == null) {
141+
// TODO remove hack
142+
printExternalIfNeed()
143+
}
139144

140145
if (isOverride) {
141146
out.print(OVERRIDE + " ")
@@ -144,6 +149,10 @@ class Stringify(
144149
out.print(OPEN + " ")
145150
}
146151

152+
if (function.extendsType != null) {
153+
out.print(INLINE + " ")
154+
}
155+
147156
if (isOperator) {
148157
out.print(OPERATOR + " ")
149158
}
@@ -159,9 +168,19 @@ 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, printDefaultValues = !isOverride, noImpl = extendsType == null)
163172

164-
if (needsNoImpl) {
173+
if (function.extendsType != null) {
174+
out.print(" { " )
175+
if (function.callSignature.returnType.type.qualifiedName != UNIT) {
176+
out.print("return ")
177+
}
178+
out.print("this.asDynamic().")
179+
out.print(name.asString())
180+
out.print("(")
181+
out.print(callSignature.params.map { it.name.asString() }.joinToString(", "))
182+
out.print(") }")
183+
} else if (needsNoImpl) {
165184
out.print(EQ_NO_IMPL)
166185
}
167186
}
@@ -174,8 +193,10 @@ class Stringify(
174193

175194
out.printIndent()
176195

177-
// TODO remove hack
178-
printExternalIfNeed()
196+
if (variable.extendsType == null) {
197+
// TODO remove hack
198+
printExternalIfNeed()
199+
}
179200

180201
// TODO extract common logic between Variable and Function
181202
if (isOverride) {
@@ -184,6 +205,10 @@ class Stringify(
184205
out.print(OPEN + " ")
185206
}
186207

208+
if (variable.extendsType != null) {
209+
out.print(INLINE + " ")
210+
}
211+
187212
out.print((if (isVar) VAR else VAL) + " ")
188213

189214
typeParams?.acceptForEach(this@Stringify, ", ", startWithIfNotEmpty = "<", endWithIfNotEmpty = "> ")
@@ -197,7 +222,15 @@ class Stringify(
197222

198223
type.printToOut(printUnitType = !needsNoImpl)
199224

200-
if (needsNoImpl) {
225+
if (variable.extendsType != null) {
226+
out.print(" get() = this.asDynamic().")
227+
out.print(name.asString())
228+
if (isVar) {
229+
out.print("; set(value) { this.asDynamic().")
230+
out.print(name.asString())
231+
out.print(" = value }")
232+
}
233+
} else if (needsNoImpl) {
201234
if (isInInterface) {
202235
out.print(NO_IMPL_PROPERTY_GETTER)
203236
if (isVar) {
@@ -256,7 +289,7 @@ class Stringify(
256289
packagePart.members.filter(isNotAnnotatedAsFake).acceptForEach(this)
257290
}
258291

259-
fun KtFunParam.printToOut(printDefaultValue: Boolean) {
292+
fun KtFunParam.printToOut(printDefaultValue: Boolean, noImpl: Boolean = true) {
260293
if (isVar) {
261294
out.print("$OPEN $VAR ")
262295
}
@@ -269,7 +302,11 @@ class Stringify(
269302
type.printToOut(printUnitType = true)
270303

271304
if (defaultValue != null && printDefaultValue) {
272-
out.print(" = $NO_IMPL /* $defaultValue */")
305+
if (noImpl) {
306+
out.print(" = $NO_IMPL /* $defaultValue */")
307+
} else {
308+
out.print(" = $defaultValue")
309+
}
273310
}
274311
}
275312

@@ -278,7 +315,7 @@ class Stringify(
278315
}
279316

280317
override fun visitCallSignature(signature: KtCallSignature) {
281-
signature.printToOut(withTypeParams = true, printUnitReturnType = true, printDefaultValues = true)
318+
signature.printToOut(withTypeParams = true, printUnitReturnType = true, printDefaultValues = true, noImpl = true)
282319
}
283320

284321
fun KtCallSignature.printTypeParams(withSpaceAfter: Boolean) {
@@ -289,15 +326,15 @@ class Stringify(
289326
endWithIfNotEmpty = ">" + if (withSpaceAfter) " " else "")
290327
}
291328

292-
fun KtCallSignature.printToOut(withTypeParams: Boolean, printUnitReturnType: Boolean, printDefaultValues: Boolean) {
329+
fun KtCallSignature.printToOut(withTypeParams: Boolean, printUnitReturnType: Boolean, printDefaultValues: Boolean, noImpl: Boolean) {
293330
if (withTypeParams) {
294331
printTypeParams(withSpaceAfter = false)
295332
}
296333

297334
out.print("(")
298335
params.forEachIndexed { index, funParam ->
299336
if (index > 0) out.print(", ")
300-
funParam.printToOut(printDefaultValues)
337+
funParam.printToOut(printDefaultValues, noImpl)
301338
}
302339
out.print(")")
303340

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ interface KtAnnotated {
9090

9191
interface KtMember : KtNode, KtNamed, KtAnnotated
9292

93+
interface KtExtensionAware : KtMember {
94+
val extendsType: KtHeritageType?
95+
}
96+
9397
// TODO should be Named?
9498
data class KtArgument(val value: Any/* TODO Any ??? */, val name: KtName? = null) : AbstractKtNode() {
9599
override fun accept(visitor: KtVisitor) {
@@ -150,13 +154,13 @@ data class KtCallSignature(
150154
data class KtFunction(
151155
override var name: KtName,
152156
val callSignature: KtCallSignature,
153-
val extendsType: KtHeritageType? = null,
157+
override val extendsType: KtHeritageType? = null,
154158
override var annotations: List<KtAnnotation> = emptyList(),
155159
val needsNoImpl: Boolean = true,
156160
val isOverride: Boolean = false,
157161
val hasOpenModifier: Boolean = false,
158162
val isOperator: Boolean = false
159-
) : KtMember, AbstractKtNode() {
163+
) : KtMember, KtExtensionAware, AbstractKtNode() {
160164
override fun accept(visitor: KtVisitor) {
161165
visitor.visitFunction(this)
162166
}
@@ -165,15 +169,15 @@ data class KtFunction(
165169
data class KtVariable(
166170
override var name: KtName,
167171
var type: KtTypeAnnotation,
168-
val extendsType: KtHeritageType? = null,
172+
override val extendsType: KtHeritageType? = null,
169173
override var annotations: List<KtAnnotation>,
170174
val typeParams: List<KtTypeParam>?,
171175
var isVar: Boolean,
172176
val needsNoImpl: Boolean = true,
173177
val isInInterface: Boolean,
174178
val isOverride: Boolean = false,
175179
val hasOpenModifier: Boolean
176-
) : KtMember, AbstractKtNode() {
180+
) : KtMember, KtExtensionAware, AbstractKtNode() {
177181
override fun accept(visitor: KtVisitor) {
178182
visitor.visitVariable(this)
179183
}
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package simple
22

3-
external fun JQuery.foo(): Unit = definedExternally
4-
external var JQuery.bar: Any get() = definedExternally; set(value) = definedExternally
5-
@nativeGetter
6-
external operator fun JQueryStatic.get(prop: String): Number? = definedExternally
7-
@nativeSetter
8-
external operator fun JQueryStatic.set(prop: String, value: Number): Unit = definedExternally
9-
external var JQueryStatic.someField: String get() = definedExternally; set(value) = definedExternally
10-
external var JQueryStatic.optionalField: Any? get() = definedExternally; set(value) = definedExternally
11-
@nativeInvoke
12-
external operator fun JQueryStatic.invoke(resourceId: String, hash: Any? = definedExternally /* null */, callback: Function<*>? = definedExternally /* null */): Unit = definedExternally
3+
inline fun Event.foo(): Unit { this.asDynamic().foo() }
4+
inline var Event.bar: Any get() = this.asDynamic().bar; set(value) { this.asDynamic().bar = value }
5+
inline operator fun Event.get(prop: String): Number? { return this.asDynamic().get(prop) }
6+
inline operator fun Event.set(prop: String, value: Number): Unit { this.asDynamic().set(prop, value) }
7+
inline var Event.someField: String get() = this.asDynamic().someField; set(value) { this.asDynamic().someField = value }
8+
inline var Event.optionalField: Any? get() = this.asDynamic().optionalField; set(value) { this.asDynamic().optionalField = value }
9+
inline operator fun Event.invoke(resourceId: String, hash: Any? = null, callback: Function<*>? = null): Unit { this.asDynamic().invoke(resourceId, hash, callback) }
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
/// <reference path="../../testDefinitelyTyped/DefinitelyTyped/jquery/jquery.d.ts" />
22

3-
interface JQuery {
3+
interface Event {
44
foo()
55
bar
6-
}
7-
8-
interface JQueryStatic {
96
[prop: string]: number;
107
someField: string;
118
optionalField?: any;
129
(resourceId:string, hash?:any, callback?:Function): void;
1310
}
14-

testData/extendExternalDeclarations/withGenericParams.d.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
@file:JsQualifier("Q")
21
package withGenericParams.Q
32

4-
external fun <T, B> Promise<T>.foo(b: B): T = definedExternally
5-
external fun <T0, T, B> Promise<T0>.foo(a: Any, b: B): T = definedExternally
6-
external var <T> Promise<T>.bar: Array<T> get() = definedExternally; set(value) = definedExternally
3+
inline fun <T, B> Promise<T>.foo(b: B): T { return this.asDynamic().foo(b) }
4+
inline fun <T0, T, B> Promise<T0>.foo(a: Any, b: B): T { return this.asDynamic().foo(a, b) }
5+
inline var <T> Promise<T>.bar: Array<T> get() = this.asDynamic().bar; set(value) { this.asDynamic().bar = value }
76

87
// ------------------------------------------------------------------------------------------
98
@file:JsModule("ref-array")

0 commit comments

Comments
 (0)