Skip to content
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
44 changes: 43 additions & 1 deletion typescript/ts-converter/src/AstConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {AstExpressionConverter} from "./ast/AstExpressionConverter";
import {ExportContext} from "./ExportContext";
import {AstVisitor} from "./AstVisitor";
import {tsInternals} from "./TsInternals";
import {ReferenceClauseDeclarationProto, ReferenceDeclarationProto} from "declarations";
import {ReferenceClauseDeclarationProto, ReferenceDeclarationProto, AccessorDeclarationProto, MemberDeclarationProto} from "declarations";

export class AstConverter {
private log = createLogger("AstConverter");
Expand Down Expand Up @@ -178,6 +178,43 @@ export class AstConverter {
return null;
}

convertAccessorDeclaration(declaration: ts.AccessorDeclaration): MemberDeclaration | null {
let typeParameterDeclarations: Array<TypeParameter> = this.convertTypeParams(declaration.typeParameters);

let parameterDeclarations = declaration.parameters.map(
(param, count) => this.convertParameterDeclaration(param, count)
);

if (ts.isIdentifier(declaration.name)) {
let method = this.astFactory.createFunctionDeclaration(
declaration.name ? declaration.name.getText() : "",
parameterDeclarations,
declaration.type ? this.convertType(declaration.type) : this.createTypeDeclaration("Unit"),
typeParameterDeclarations,
this.convertModifiers(declaration.modifiers),
this.convertBlock(declaration.body),
"__NO_UID__"
);

let accessor = new AccessorDeclarationProto();
accessor.setMethod(method);
if (ts.isGetAccessorDeclaration(declaration)) {
accessor.setAccess(AccessorDeclarationProto.ACCESS.READ)
} else if (ts.isSetAccessorDeclaration(declaration)) {
accessor.setAccess(AccessorDeclarationProto.ACCESS.WRITE)
} else {
throw Error("Invalid accessor" + declaration)
}

let memberProto = new MemberDeclarationProto();
memberProto.setAccessor(accessor);
return memberProto;
}

return null;
}


convertTypeParams(nativeTypeDeclarations: ts.NodeArray<ts.TypeParameterDeclaration> | undefined): Array<TypeParameter> {
let typeParameterDeclarations: Array<TypeParameter> = [];

Expand Down Expand Up @@ -653,6 +690,11 @@ export class AstConverter {
this.convertConstructorDeclaration(memberDeclaration as ts.ConstructorDeclaration).map(member => {
this.registerDeclaration(member, members);
});
} else if (ts.isSetAccessorDeclaration(memberDeclaration) || ts.isGetAccessorDeclaration(memberDeclaration)) {
let accessorDeclaration = this.convertAccessorDeclaration(memberDeclaration as ts.AccessorDeclaration);
if (accessorDeclaration != null) {
this.registerDeclaration(accessorDeclaration, members)
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions typescript/ts-converter/src/ast/ast.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AccessorDeclarationProto,
BlockDeclarationProto,
CallSignatureDeclarationProto,
ClassDeclarationProto,
Expand Down Expand Up @@ -59,6 +60,7 @@ export type NameEntity = NameDeclarationProto;
export type ParameterDeclaration = ParameterDeclarationProto;
export type TypeDeclaration = ParameterValueDeclarationProto;
export type PropertyDeclaration = PropertyDeclarationProto;
export type AccessorDeclaration = AccessorDeclarationProto;
export type ReferenceEntity = ReferenceDeclarationProto;
export type SourceBundle = SourceBundleDeclarationProto;
export type SourceFileDeclaration = SourceFileDeclarationProto;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jetbrains.dukat.tsLowerings

import org.jetbrains.dukat.ownerContext.NodeOwner
import org.jetbrains.dukat.tsmodel.AccessorDeclaration
import org.jetbrains.dukat.tsmodel.ClassDeclaration
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
import org.jetbrains.dukat.tsmodel.Declaration
Expand Down Expand Up @@ -29,6 +30,7 @@ import org.jetbrains.dukat.tsmodel.types.UnionTypeDeclaration

interface DeclarationLowering {
fun lowerVariableDeclaration(declaration: VariableDeclaration, owner: NodeOwner<ModuleDeclaration>): VariableDeclaration
fun lowerAccessorDeclaration(declaration: AccessorDeclaration, onwer:NodeOwner<MemberDeclaration>): AccessorDeclaration
fun lowerFunctionDeclaration(declaration: FunctionDeclaration, owner: NodeOwner<FunctionOwnerDeclaration>): FunctionDeclaration
fun lowerClassDeclaration(declaration: ClassDeclaration, owner: NodeOwner<ModuleDeclaration>): ClassDeclaration
fun lowerInterfaceDeclaration(declaration: InterfaceDeclaration, owner: NodeOwner<ModuleDeclaration>): InterfaceDeclaration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.jetbrains.dukat.tsLowerings

import org.jetbrains.dukat.logger.Logging
import org.jetbrains.dukat.ownerContext.NodeOwner
import org.jetbrains.dukat.tsmodel.AccessorDeclaration
import org.jetbrains.dukat.tsmodel.CallSignatureDeclaration
import org.jetbrains.dukat.tsmodel.ClassDeclaration
import org.jetbrains.dukat.tsmodel.ClassLikeDeclaration
Expand Down Expand Up @@ -77,6 +78,7 @@ interface DeclarationTypeLowering : DeclarationLowering {
is MethodSignatureDeclaration -> lowerMethodSignatureDeclaration(declaration, newOwner)
is CallSignatureDeclaration -> lowerCallSignatureDeclaration(declaration, newOwner)
is IndexSignatureDeclaration -> lowerIndexSignatureDeclaration(declaration, newOwner)
is AccessorDeclaration -> lowerAccessorDeclaration(declaration, newOwner)
else -> {
logger.debug("[${this}] skipping ${declaration}")
declaration
Expand All @@ -94,6 +96,10 @@ interface DeclarationTypeLowering : DeclarationLowering {
)
}

override fun lowerAccessorDeclaration(declaration: AccessorDeclaration, onwer:NodeOwner<MemberDeclaration>):AccessorDeclaration {
return declaration.copy()
}

override fun lowerFunctionDeclaration(declaration: FunctionDeclaration, owner: NodeOwner<FunctionOwnerDeclaration>): FunctionDeclaration {
return declaration.copy(
parameters = declaration.parameters.map { parameter -> lowerParameterDeclaration(parameter, owner.wrap(declaration)) },
Expand Down
10 changes: 10 additions & 0 deletions typescript/ts-model-proto/src/Declarations.proto
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ message PropertyDeclarationProto {
repeated ModifierDeclarationProto modifiers = 6;
}

message AccessorDeclarationProto {
FunctionDeclarationProto method = 1;
enum ACCESS {
READ = 0;
WRITE = 1;
}
ACCESS access = 2;
}

message ModifierDeclarationProto {
string token = 1;
}
Expand All @@ -156,6 +165,7 @@ message MemberDeclarationProto {
MethodSignatureDeclarationProto methodSignature = 5;
PropertyDeclarationProto property = 6;
ObjectLiteralDeclarationProto objectLiteral = 7;
AccessorDeclarationProto accessor = 8;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.jetbrains.dukat.tsmodel

data class AccessorDeclaration(
val method: FunctionDeclaration,
val access: ACCESS
) : MemberDeclaration {
enum class ACCESS {
WRITE,
READ
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.jetbrains.dukat.tsmodel.types.TupleDeclaration
import org.jetbrains.dukat.tsmodel.types.TypeDeclaration
import org.jetbrains.dukat.tsmodel.types.TypeParamReferenceDeclaration
import org.jetbrains.dukat.tsmodel.types.UnionTypeDeclaration
import org.jetbrains.dukat.tsmodelproto.AccessorDeclarationProto
import org.jetbrains.dukat.tsmodelproto.ArrayLiteralExpressionDeclarationProto
import org.jetbrains.dukat.tsmodelproto.BigIntLiteralExpressionDeclarationProto
import org.jetbrains.dukat.tsmodelproto.BinaryExpressionDeclarationProto
Expand Down Expand Up @@ -167,6 +168,11 @@ fun InterfaceDeclarationProto.convert(): InterfaceDeclaration {
)
}

fun AccessorDeclarationProto.convert(): AccessorDeclaration {
val access:AccessorDeclaration.ACCESS = if (this.accessValue == AccessorDeclarationProto.ACCESS.WRITE_VALUE) AccessorDeclaration.ACCESS.WRITE else AccessorDeclaration.ACCESS.READ
return AccessorDeclaration(method.convert(),access)
}

fun BlockDeclarationProto.convert(): BlockDeclaration {
return BlockDeclaration(
statements = statementsList.map { it.convert() }
Expand Down Expand Up @@ -350,6 +356,7 @@ fun MemberDeclarationProto.convert(): MemberDeclaration {
hasProperty() -> property.convert()
hasIndexSignature() -> indexSignature.convert()
hasCallSignature() -> callSignature.convert()
hasAccessor() -> accessor.convert()
else -> throw Exception("unknown MemberEntityProto: ${this}")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ private class LowerDeclarationsToNodes(private val fileName: String, private val

private fun PropertyDeclaration.isStatic() = modifiers.contains(ModifierDeclaration.STATIC_KEYWORD)

fun convertPropertyFromAccessorDeclaration(declaration: AccessorDeclaration):PropertyNode {
var type = declaration.method.type
if (declaration.access == AccessorDeclaration.ACCESS.WRITE) {
val customType = declaration.method.parameters.firstOrNull()?.type
?: {
raiseConcern("Invalid parameters: " + declaration.method.parameters, {})
type
}()
type = customType
}

return PropertyNode(
declaration.method.name,
type,
convertTypeParameters(declaration.method.typeParameters),

declaration.method.isStatic(),
declaration.access == AccessorDeclaration.ACCESS.READ,
declaration.access == AccessorDeclaration.ACCESS.WRITE,

true
)
}

fun convertPropertyDeclaration(declaration: PropertyDeclaration): PropertyNode {
return PropertyNode(
declaration.name,
Expand Down Expand Up @@ -411,6 +435,7 @@ private class LowerDeclarationsToNodes(private val fileName: String, private val
true,
null
))
is AccessorDeclaration -> listOf(convertPropertyFromAccessorDeclaration(declaration))
is MethodSignatureDeclaration -> listOf(lowerMethodSignatureDeclaration(declaration)).mapNotNull { it }
is CallSignatureDeclaration -> listOf(declaration.convert())
is PropertyDeclaration -> listOf(convertPropertyDeclaration(declaration))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ private class DocumentConverter(private val documentRootNode: DocumentRootNode,
static = static,
override = null,
immutable = getter && !setter,
getter = false,
setter = false,
getter = getter,
setter = setter,
open = open
)
else -> raiseConcern("unprocessed MemberNode: ${this}") { null }
Expand Down Expand Up @@ -457,8 +457,52 @@ private class DocumentConverter(private val documentRootNode: DocumentRootNode,
}
}

/**
* in kotlin writable accessor is readable too
*
* Convert records:
* "write accessor" + "read accessor" => "write accessor"
* "read accessor" => "read accessor"
* "write accessor" => remove (write and not read accessor is not possible in kotlin)
*/
private fun filterAccessors(className:String, source: List<MemberNode>): List<MemberNode> {
val writeAccessors = mutableMapOf<String, PropertyNode>()
val readAccessors = mutableMapOf<String, PropertyNode>()

for (member in source) {
if (member is PropertyNode) {
if (member.getter) {
readAccessors.put(member.name, member)
}
if (member.setter) {
writeAccessors.put(member.name, member)
}
}
}

val target = mutableListOf<MemberNode>()
source.forEach { member->
if (member is PropertyNode) {
val write = writeAccessors.get(member.name)
val read = readAccessors.get(member.name)
if (write != null && read != null) {
target.add(write)
} else if (read != null) {
target.add(read)
} else if (write != null) {
logger.warn("write only accessor: $className::${member.name} now not supported")
} else {
target.add(member)
}
} else {
target.add(member)
}
}
return target
}

private fun ClassNode.convertToClassModel(): TopLevelModel {
val membersSplitted = split(members)
val membersSplitted = split(filterAccessors(name.toString(), members))

val generatedMethods = mutableListOf<MemberModel>()
val parentModelEntities = convertParentEntities(parentEntities) {
Expand Down