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

Commit 1e2c8b0

Browse files
committed
Introduce KtName and KtQualifiedName to make escaping more accurate
Fix #73
1 parent e405ec0 commit 1e2c8b0

16 files changed

+149
-122
lines changed

src/ast/kotlin/Stringify.kt

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class Stringify(
6868
}
6969

7070
private fun printAnnotation(annotation: KtAnnotation) {
71-
out.print(annotation.escapedName)
71+
out.print(annotation.name.asString())
7272
annotation.parameters.acceptForEach(this, delimiter = ", ", startWithIfNotEmpty = "(", endWithIfNotEmpty = ")")
7373
}
7474

@@ -86,11 +86,12 @@ class Stringify(
8686

8787
out.print(kind.keyword)
8888

89-
if (name.isNotEmpty()) {
90-
out.print(" ")
89+
val nameToPrint = name.asString()
90+
91+
if (nameToPrint.isNotEmpty()) {
92+
out.print(" $nameToPrint")
9193
}
9294

93-
out.print(escapedName)
9495
typeParams?.acceptForEach(this@Stringify, ", ", startWithIfNotEmpty = "<", endWithIfNotEmpty = ">")
9596

9697
if (paramsOfConstructors.size == 1) {
@@ -156,7 +157,7 @@ class Stringify(
156157
out.print(".")
157158
}
158159

159-
out.print(escapedName)
160+
out.print(name.asString())
160161

161162
callSignature.printToOut(withTypeParams = false, printUnitReturnType = needsNoImpl, printDefaultValues = !isOverride)
162163

@@ -192,7 +193,7 @@ class Stringify(
192193
out.print(".")
193194
}
194195

195-
out.print(name.escapeIfNeed())
196+
out.print(name.asString())
196197

197198
type.printToOut(printUnitType = !needsNoImpl)
198199

@@ -263,7 +264,7 @@ class Stringify(
263264
out.print(VARARG + " ")
264265
}
265266

266-
out.print(escapedName)
267+
out.print(name.asString())
267268

268269
type.printToOut(printUnitType = true)
269270

@@ -304,12 +305,12 @@ class Stringify(
304305
}
305306

306307
override fun visitEnumEntry(enumEntry: KtEnumEntry) {
307-
out.printWithIndent(enumEntry.escapedName)
308+
out.printWithIndent(enumEntry.name.asString())
308309
enumEntry.value?.let { out.print(" /* = $it */") }
309310
}
310311

311312
override fun visitTypeParam(typeParam: KtTypeParam) {
312-
out.print(typeParam.escapedName)
313+
out.print(typeParam.name.asString())
313314
typeParam.upperBound?.let {
314315
out.print(" : ")
315316
it.accept(this)
@@ -335,20 +336,20 @@ class Stringify(
335336
if (isNullable) out.print("(")
336337

337338
val params = callSignature.params.joinToString(", ") {
338-
it.name + it.type.stringify() + (it.defaultValue?.let { " /*= $it*/" } ?: "")
339+
it.name.asString() + it.type.stringify() + (it.defaultValue?.let { " /*= $it*/" } ?: "")
339340
}
340341
val typeAsString = "($params) -> ${callSignature.returnType.type.stringify()}"
341342
out.print(typeAsString)
342343

343344
if (isNullable) out.print(")")
344345
}
345346
else {
346-
out.print(if (!isLambda) escapedName else name)
347+
out.print(qualifiedName.asString())
347348

348349
typeArgs.acceptForEach(this@Stringify, ", ", startWithIfNotEmpty = "<", endWithIfNotEmpty = ">")
349350
}
350351

351-
if (isNullable && name != DYNAMIC) {
352+
if (isNullable && qualifiedName != DYNAMIC) {
352353
out.print("?")
353354
}
354355

@@ -363,7 +364,10 @@ class Stringify(
363364
}
364365

365366
override fun visitHeritageType(heritageType: KtHeritageType) {
366-
out.print(heritageType.name)
367+
visitType(heritageType.type)
368+
heritageType.byExpression?.let {
369+
out.print(" by $it")
370+
}
367371
}
368372

369373
override fun visitArgument(argument: KtArgument) {

src/ast/kotlin/ast.kt

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ package ts2kt.kotlin.ast
1818

1919
import ts2kt.DYNAMIC
2020
import ts2kt.UNIT
21+
import ts2kt.escapeIfNeed
2122

22-
val MODULE = "module"
23-
private val FAKE = "fake"
23+
val MODULE = KtName("module")
24+
private val FAKE = KtName("fake")
2425

2526
val FAKE_ANNOTATION = KtAnnotation(FAKE)
2627
val DEFAULT_FAKE_ANNOTATION = listOf(FAKE_ANNOTATION)
@@ -62,9 +63,24 @@ class KtPackagePart(
6263
}
6364
}
6465

66+
data class KtName(val value: String) {
67+
fun asString(): String = value.escapeIfNeed()
68+
69+
companion object {
70+
val NO_NAME = KtName("")
71+
}
72+
}
73+
74+
data class KtQualifiedName(val name: KtName, val qualifier: KtQualifiedName? = null) {
75+
76+
constructor(name: String, qualifier: KtQualifiedName? = null) : this(KtName(name), qualifier)
77+
78+
fun asString(): String = (qualifier?.let { it.asString() + "." } ?: "") + name.asString()
79+
}
80+
6581
interface KtNamed {
6682
// TODO: make it immutable
67-
var name: String
83+
var name: KtName
6884
}
6985

7086
interface KtAnnotated {
@@ -75,14 +91,13 @@ interface KtAnnotated {
7591
interface KtMember : KtNode, KtNamed, KtAnnotated
7692

7793
// TODO should be Named?
78-
// TODO should we escape name here?
79-
data class KtArgument(val value: Any/* TODO Any ??? */, val name: String? = null) : AbstractKtNode() {
94+
data class KtArgument(val value: Any/* TODO Any ??? */, val name: KtName? = null) : AbstractKtNode() {
8095
override fun accept(visitor: KtVisitor) {
8196
visitor.visitArgument(this)
8297
}
8398
}
8499

85-
data class KtAnnotation(override var name: String, val parameters: List<KtArgument> = listOf()) : KtNamed, AbstractKtNode() {
100+
data class KtAnnotation(override var name: KtName, val parameters: List<KtArgument> = listOf()) : KtNamed, AbstractKtNode() {
86101
override fun accept(visitor: KtVisitor) {
87102
visitor.visitAnnotation(this)
88103
}
@@ -98,7 +113,7 @@ enum class KtClassKind(val keyword: String, val bracesAlwaysRequired: Boolean =
98113

99114
data class KtClassifier(
100115
val kind: KtClassKind,
101-
override var name: String,
116+
override var name: KtName,
102117
val paramsOfConstructors: List<List<KtFunParam>>,
103118
val typeParams: List<KtTypeParam>?,
104119
val parents: List<KtHeritageType>,
@@ -112,7 +127,7 @@ data class KtClassifier(
112127
}
113128

114129
data class KtFunParam(
115-
override var name: String,
130+
override var name: KtName,
116131
val type: KtTypeAnnotation,
117132
val defaultValue: Any? = null,
118133
val isVar: Boolean = false
@@ -133,7 +148,7 @@ data class KtCallSignature(
133148
}
134149

135150
data class KtFunction(
136-
override var name: String,
151+
override var name: KtName,
137152
val callSignature: KtCallSignature,
138153
val extendsType: KtHeritageType? = null,
139154
override var annotations: List<KtAnnotation> = emptyList(),
@@ -148,7 +163,7 @@ data class KtFunction(
148163
}
149164

150165
data class KtVariable(
151-
override var name: String,
166+
override var name: KtName,
152167
var type: KtTypeAnnotation,
153168
val extendsType: KtHeritageType? = null,
154169
override var annotations: List<KtAnnotation>,
@@ -164,15 +179,15 @@ data class KtVariable(
164179
}
165180
}
166181

167-
data class KtEnumEntry(override var name: String, val value: String? = null) : KtMember, AbstractKtNode() {
182+
data class KtEnumEntry(override var name: KtName, val value: String? = null) : KtMember, AbstractKtNode() {
168183
override var annotations = listOf<KtAnnotation>()
169184

170185
override fun accept(visitor: KtVisitor) {
171186
visitor.visitEnumEntry(this)
172187
}
173188
}
174189

175-
data class KtHeritageType(override var name: String) : KtNamed, AbstractKtNode() {
190+
data class KtHeritageType(var type: KtType, val byExpression: String? = null) : AbstractKtNode() {
176191
override fun accept(visitor: KtVisitor) {
177192
visitor.visitHeritageType(this)
178193
}
@@ -193,17 +208,17 @@ data class KtTypeUnion(val possibleTypes: List<KtType>) : AbstractKtNode() {
193208

194209
/**
195210
* A reference to a type such as String or Map<String,List<T>> such as for a variable, function param or return type.
196-
* @param name the name of the type such as String or Map
211+
* @param qualifiedName the name of the type such as String or Map
197212
* @param typeArgs the type params such as [String, List<T>], defaulting to empty
198213
* @param comment a comment about the type, currently used to document intersection types, defaulting to null.
199214
*/
200215
data class KtType(
201-
override var name: String,
216+
var qualifiedName: KtQualifiedName,
202217
val typeArgs: List<KtType> = emptyList(),
203218
val comment: String? = null,
204219
val isNullable: Boolean = false,
205220
val callSignature: KtCallSignature? = null
206-
) : KtNamed, AbstractKtNode() {
221+
) : AbstractKtNode() {
207222

208223
override fun accept(visitor: KtVisitor) {
209224
visitor.visitType(this)
@@ -212,10 +227,12 @@ data class KtType(
212227
val isLambda: Boolean get() = callSignature != null
213228

214229
// TODO make extension function
215-
fun isUnit() = escapedName == UNIT && !isNullable && !isLambda
230+
fun isUnit() = qualifiedName == UNIT && !isNullable && !isLambda
216231
}
217232

218-
data class KtTypeParam(override var name: String, val upperBound: KtType? = null) : KtNamed, AbstractKtNode() {
233+
fun starType() = KtType(KtQualifiedName("*"))
234+
235+
data class KtTypeParam(override var name: KtName, val upperBound: KtType? = null) : KtNamed, AbstractKtNode() {
219236
override fun accept(visitor: KtVisitor) {
220237
visitor.visitTypeParam(this)
221238
}

src/ast/kotlin/astUtils.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package ts2kt.kotlin.ast
22

3-
import ts2kt.escapeIfNeed
4-
import ts2kt.utils.join
5-
63

74
// TODO: review usages
85
fun KtNode.stringify() = stringify(null, false)
@@ -23,12 +20,9 @@ fun KtClassifier.hasModuleAnnotation() = annotations.any { it.name == MODULE }
2320
fun KtClassifier.getClassObject(): KtClassifier? =
2421
this.members.firstOrNull { it is KtClassifier && it.kind === KtClassKind.COMPANION_OBJECT } as? KtClassifier
2522

26-
val KtNamed.escapedName: String
27-
get() = name.escapeIfNeed()
28-
2923
fun createFunctionType(parameters: List<KtFunParam>, returnType: KtType, isNullable: Boolean = false): KtType {
3024
return KtType(
31-
"Function",
25+
KtQualifiedName("Function"),
3226
callSignature = KtCallSignature(parameters, null, KtTypeAnnotation(returnType)),
3327
isNullable = isNullable
3428
)

src/ast/typescript/typeScriptAstUtils.kt

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ import ts2kt.kotlin.ast.*
2222
import ts2kt.utils.*
2323
import typescriptServices.ts.*
2424

25-
val ANY = "Any"
26-
val NOTHING = "Nothing"
27-
val NUMBER = "Number"
28-
val STRING = "String"
29-
val BOOLEAN = "Boolean"
30-
val UNIT = "Unit"
31-
val DYNAMIC = "dynamic"
32-
val ARRAY = "Array"
25+
val ANY = KtQualifiedName("Any")
26+
val NOTHING = KtQualifiedName("Nothing")
27+
val NUMBER = KtQualifiedName("Number")
28+
val STRING = KtQualifiedName("String")
29+
val BOOLEAN = KtQualifiedName("Boolean")
30+
val UNIT = KtQualifiedName("Unit")
31+
val DYNAMIC = KtQualifiedName("dynamic")
32+
val ARRAY = KtQualifiedName("Array")
3333

3434
val NOTHING_TYPE = KtType(NOTHING, isNullable = true)
3535

@@ -53,6 +53,7 @@ fun String.escapeIfNeed(): String {
5353
}
5454

5555
private fun String.isIdentifier(): Boolean {
56+
if (isEmpty()) return false
5657
if (this in SHOULD_BE_ESCAPED) return false
5758
if (!this[0].isIdentifierStart()) return false
5859
return this.drop(1).all { it.isIdentifierPart() }
@@ -117,7 +118,7 @@ private fun ParameterDeclaration.toKotlinParam(type: KtType): KtFunParam {
117118
val isVar = ModifierFlags.AccessibilityModifier in getCombinedModifierFlags(this)
118119

119120
val isOptional = questionToken != null
120-
return KtFunParam(name,
121+
return KtFunParam(KtName(name),
121122
KtTypeAnnotation(type, isVararg = isVararg),
122123
if (defaultValue == null && isOptional) "null" else defaultValue,
123124
isVar)
@@ -186,7 +187,10 @@ fun NodeArray<TypeParameterDeclaration>.toKotlinTypeParams(typeMapper: ObjectTyp
186187
fun TypeParameterDeclaration.toKotlinTypeParam(typeMapper: ObjectTypeToKotlinTypeMapper): KtTypeParam {
187188
val type = typeMapper.mapType(this)
188189
val upperBound = constraint?.let { typeMapper.mapType(it) }
189-
return KtTypeParam(type.name, upperBound)
190+
191+
assert(type.qualifiedName.qualifier == null, "type.qualifiedName.qualifier expected to be null, but ${type.qualifiedName.qualifier}")
192+
193+
return KtTypeParam(type.qualifiedName.name, upperBound)
190194
}
191195

192196
fun SignatureDeclaration.toKotlinCallSignatureOverloads(typeMapper: ObjectTypeToKotlinTypeMapper): List<KtCallSignature> {
@@ -262,7 +266,7 @@ fun TypeNode.toKotlinType(typeMapper: ObjectTypeToKotlinTypeMapper): KtType {
262266
SyntaxKind.TypeReference -> (this.cast<TypeReferenceNode>()).toKotlinTypeUnion(typeMapper).singleType
263267
SyntaxKind.ExpressionWithTypeArguments -> (this.cast<ExpressionWithTypeArguments>()).toKotlinType(typeMapper)
264268

265-
SyntaxKind.Identifier -> KtType((this.cast<Identifier>()).unescapedText)
269+
SyntaxKind.Identifier -> KtType(KtQualifiedName((this.cast<Identifier>()).unescapedText))
266270
SyntaxKind.TypeLiteral -> (this.cast<TypeLiteralNode>()).toKotlinType(typeMapper)
267271

268272
SyntaxKind.UnionType -> (this.cast<UnionTypeNode>()).toKotlinTypeUnion(typeMapper).singleType
@@ -283,12 +287,12 @@ fun TypeNode.toKotlinType(typeMapper: ObjectTypeToKotlinTypeMapper): KtType {
283287
}
284288
}
285289

286-
fun EntityName.toKotlinTypeName(): String {
290+
fun EntityName.toKotlinTypeName(): KtQualifiedName {
287291
return when (kind as Any) {
288292
SyntaxKind.Identifier ->
289-
(this as Identifier).unescapedText
293+
KtQualifiedName((this as Identifier).unescapedText)
290294
else ->
291-
(this as QualifiedName).left.toKotlinTypeName() + "." + this.right.unescapedText
295+
KtQualifiedName((this as QualifiedName).right.unescapedText, this.left.toKotlinTypeName())
292296
}
293297
}
294298

@@ -302,8 +306,8 @@ private fun TypeReferenceNode.toKotlinTypeIgnoringTypeAliases(typeMapper: Object
302306

303307
return when (name) {
304308
// TODO: HACKS
305-
"Function" -> KtType(name, listOf(KtType("*")))
306-
"Object" -> KtType(ANY)
309+
KtQualifiedName("Function") -> KtType(name, listOf(starType()))
310+
KtQualifiedName("Object") -> KtType(ANY)
307311

308312
else -> KtType(name, typeArguments?.arr?.map { typeMapper.mapType(it) } ?: emptyList())
309313
}
@@ -312,23 +316,23 @@ private fun TypeReferenceNode.toKotlinTypeIgnoringTypeAliases(typeMapper: Object
312316
fun ExpressionWithTypeArguments.toKotlinType(typeMapper: ObjectTypeToKotlinTypeMapper): KtType {
313317
val name = expression.stringifyQualifiedName()
314318

315-
return KtType(name ?: "???", typeArguments?.arr?.map { typeMapper.mapType(it) } ?: emptyList())
319+
return KtType(name ?: KtQualifiedName("???"), typeArguments?.arr?.map { typeMapper.mapType(it) } ?: emptyList())
316320
}
317321

318-
private fun PropertyAccessExpression.stringify(): String {
322+
private fun PropertyAccessExpression.toKtQualifiedName(): KtQualifiedName {
319323
val identifier = identifierName.unescapedText
320324

321-
val qualifier = expression?.stringifyQualifiedName() ?: return identifier
325+
val qualifier = expression?.stringifyQualifiedName()
322326

323-
return qualifier + "." + identifier
327+
return KtQualifiedName(identifier, qualifier)
324328
}
325329

326330
private fun Node.stringifyQualifiedName() = when (kind as Any) {
327331
SyntaxKind.Identifier ->
328-
(this.cast<Identifier>()).unescapedText
332+
KtQualifiedName((this.cast<Identifier>()).unescapedText)
329333

330334
SyntaxKind.PropertyAccessExpression ->
331-
(this.cast<PropertyAccessExpression>()).stringify()
335+
(this.cast<PropertyAccessExpression>()).toKtQualifiedName()
332336

333337
else -> reportUnsupportedNode(this)
334338
}
@@ -386,7 +390,7 @@ fun TypePredicateNode.toKotlinType(typeMapper: ObjectTypeToKotlinTypeMapper): Kt
386390
fun ClassOrInterfaceDeclaration.toKotlinType(typeMapper: ObjectTypeToKotlinTypeMapper): KtType {
387391
val name = identifierName!!.unescapedText
388392

389-
return KtType(name, typeParameters?.arr?.map { KtType(it.identifierName.unescapedText) } ?: emptyList())
393+
return KtType(KtQualifiedName(name), typeParameters?.arr?.map { KtType(KtQualifiedName(it.identifierName.unescapedText)) } ?: emptyList())
390394
}
391395

392396
fun forEachChild(visitor: Visitor, node: Node) {

0 commit comments

Comments
 (0)