diff --git a/sample_AST_breakdown.txt b/sample_AST_breakdown.txt new file mode 100644 index 0000000..675a638 --- /dev/null +++ b/sample_AST_breakdown.txt @@ -0,0 +1,88 @@ +this is probably a companion object +CLASS NAME: MyApp +CLASS PROPERTIES: +CLASS METHODS: +CLASS NAME: BottomViewController +CLASS PROPERTIES: + view: BottomView + mondays: CatSchedule("Tom Mariano", "Meowsers", "1015 High Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1010 8 Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + tuesdays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + wednesdays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + thursdays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + fridays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable +CLASS METHODS: + Method(name=changeCatAvi, parameters=[Property(valOrVar=val, propertyName=catSchedule, propertyType=CatSchedule)], returnType=Unit, methodStatements=[, val rectangle: {"name":"rectangle"} = = , val image: {"name":"image"} = = , ], viewNodesAffected=[]) + Method(name=editCatSchedule, parameters=[Property(valOrVar=val, propertyName=catSchedule, propertyType=CatSchedule)], returnType=Unit, methodStatements=[val catScheduleScope: {"name":"catScheduleScope"} = = , , ], viewNodesAffected=[]) +CLASS NAME: CatScheduleEvent +CLASS PROPERTIES: + view: BottomView + mondays: CatSchedule("Tom Mariano", "Meowsers", "1015 High Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1010 8 Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + tuesdays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + wednesdays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + thursdays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable + fridays: CatSchedule("Tom Mariano", "Meowsers", "1110 6th Street", "3:00PM", "/kitty/kitty1.png").observableCatSchedule("John Hill", "Tom", "1115 6th Street", "4:00PM", "/kitty/kitty2.png").observableCatSchedule("Louise Vargas", "Mr. Whiskers", "1120 6th Street", "4:30PM", "/kitty/kitty3.png").observableCatSchedule("Dale Benton", "Pepper", "2111 8th Street", "7:00PM", "/kitty/kitty4.png").observableCatSchedule("Tucker Harrison", "Princess", "2267 8th Street", "8:00PM", "/kitty/kitty5.png").observable +CLASS METHODS: + Method(name=changeCatAvi, parameters=[Property(valOrVar=val, propertyName=catSchedule, propertyType=CatSchedule)], returnType=Unit, methodStatements=[, val rectangle: {"name":"rectangle"} = = , val image: {"name":"image"} = = , ], viewNodesAffected=[]) + Method(name=editCatSchedule, parameters=[Property(valOrVar=val, propertyName=catSchedule, propertyType=CatSchedule)], returnType=Unit, methodStatements=[val catScheduleScope: {"name":"catScheduleScope"} = = , , ], viewNodesAffected=[]) +CLASS NAME: NeighborhoodController +CLASS PROPERTIES: + view: NeighborhoodView +CLASS METHODS: + Method(name=housePane, parameters=[Property(valOrVar=val, propertyName=position, propertyType=Pos)], returnType=StackPane, methodStatements=[val houseNum: {"name":"houseNum"} = = , ], viewNodesAffected=[]) + Method(name=grassPane, parameters=[], returnType=StackPane, methodStatements=[], viewNodesAffected=[]) + Method(name=verticalStreetPane, parameters=[], returnType=StackPane, methodStatements=[], viewNodesAffected=[]) + Method(name=horizontalStreetPane, parameters=[], returnType=StackPane, methodStatements=[], viewNodesAffected=[]) + Method(name=crossStreetPane, parameters=[], returnType=StackPane, methodStatements=[], viewNodesAffected=[]) + Method(name=random, parameters=[], returnType=Unit, methodStatements=[ADD], viewNodesAffected=[]) +CLASS NAME: CatSchedule +CLASS PROPERTIES: + ownerNameProperty: SimpleStringProperty + catNameProperty: SimpleStringProperty + addressProperty: SimpleStringProperty + timeProperty: SimpleStringProperty + catImageProperty: SimpleStringProperty +CLASS METHODS: +CLASS NAME: CatScheduleModel +CLASS PROPERTIES: + ownerNameProperty: SimpleStringProperty + catNameProperty: SimpleStringProperty + addressProperty: SimpleStringProperty + timeProperty: SimpleStringProperty + catImageProperty: SimpleStringProperty +CLASS METHODS: +CLASS NAME: CatScheduleScope +CLASS PROPERTIES: + ownerNameProperty: SimpleStringProperty + catNameProperty: SimpleStringProperty + addressProperty: SimpleStringProperty + timeProperty: SimpleStringProperty + catImageProperty: SimpleStringProperty +CLASS METHODS: +CLASS NAME: NeighborhoodView +CLASS PROPERTIES: + controller: NeighborhoodController + root: stackpane +CLASS METHODS: +CLASS NAME: Editor +CLASS PROPERTIES: + ownerNameField: singleAssign + catNameField: singleAssign + timeField: singleAssign + root: hbox +CLASS METHODS: + Method(name=save, parameters=[], returnType=Unit, methodStatements=[, val catSchedule: {"name":"catSchedule"} = = , , ], viewNodesAffected=[]) +CLASS NAME: BottomView +CLASS PROPERTIES: + controller: BottomViewController + model: CatScheduleModel + weekdays: listOf + root: hbox +CLASS METHODS: +CLASS NAME: MainView +CLASS PROPERTIES: + root: borderpane +CLASS METHODS: +DETECTED LAMBDA ELEMENTS IN PROJECT: +Editor=[textfield, textfield, textfield, button, action] +DERIVING INPUTS: +Editor=[textfield, textfield, textfield, button, action] \ No newline at end of file diff --git a/src/main/kotlin/com/github/ast/parser/KParser.kt b/src/main/kotlin/com/github/ast/parser/KParser.kt index 711e2bf..1fc6598 100644 --- a/src/main/kotlin/com/github/ast/parser/KParser.kt +++ b/src/main/kotlin/com/github/ast/parser/KParser.kt @@ -42,28 +42,35 @@ class KParser : Controller() { private fun breakdownClassMethod(method: Node.Decl.Func, classMethods: ArrayList) { val methodJson = gson.toJsonTree(method).asJsonObject val methodStatements = ArrayList() - val methodStmts = methodJson.body().block().stmts() - if (methodStmts.size() > 0) { - methodStmts.forEach { statement -> - val stmt = statement.asJsonObject - when { - stmt.has("expr") -> - methodStatements.add(breakdownExpr(stmt.expr(), "")) - stmt.has("decl") -> - methodStatements.add(breakdownDecl(stmt.decl(), "")) - else -> println("stmt has$stmt") + if (methodJson.body().has("block")) { + val methodStmts = methodJson.body().block().stmts() + if (methodStmts.size() > 0) { + methodStmts.forEach { statement -> + val stmt = statement.asJsonObject + when { + stmt.has("expr") -> + methodStatements.add(breakdownExpr(stmt.expr(), "")) + stmt.has("decl") -> + methodStatements.add(breakdownDecl(stmt.decl(), "")) + else -> println("stmt has$stmt") + } } } + } else { + methodStatements.add(breakdownBinaryOperation((methodJson.body().expr()), "")) } val parameters = ArrayList() methodJson.params().forEach { parameter -> val param = parameter.asJsonObject - val paramType = param.type().ref().pieces().getObject(0).name() + val paramType = param.type().ref().getType() parameters.add(Property("val", param.name(), paramType)) } - val returnType = methodJson.type().ref().pieces().getObject(0).name() + var returnType = "Unit" + if (methodJson.has("type")) { + returnType = methodJson.type().ref().getType() + } // TODO write a mechanism to detect nodes per function after AST parse job is complete classMethods.add(Method( @@ -71,13 +78,26 @@ class KParser : Controller() { parameters = parameters, returnType = returnType, methodStatements = methodStatements, - viewNodesAffected = ArrayList())) + viewNodesAffected = ArrayList())) } private fun breakdownDecl(decl: JsonObject, buildStmt: String): String { val isolated = decl.vars().getObject(0) val isolatedName = isolated.name() - val property = getProperty(decl, isolated, isolatedName) + val property = when { + decl.expr().has("expr") -> getProperty( + decl, + isolated, + isolatedName) + decl.expr().has("lhs") && + decl.expr().has("oper") && + decl.expr().has("rhs") -> Property( + valOrVar(decl), + isolatedName, + breakdownBinaryOperation(decl.expr(), "") + ) + else -> TODO() + } val declaration = "$buildStmt${property.valOrVar} $isolatedName: $isolated =" return "$declaration = ${breakdownExpr(decl, buildStmt)}" } @@ -99,25 +119,38 @@ class KParser : Controller() { */ private fun getArguments(arguments: JsonArray, buildStmt: String): String { var buildArgs = "$buildStmt(" - arguments.forEachIndexed { index, argument -> - val elem = argument.asJsonObject.expr().elems().getObject(0) - when { - elem.has("str") -> buildArgs += "${elem.get("str")}" - elem.has("expr") -> buildArgs += breakdownExpr(elem, buildArgs) - else -> println("Looks like this element type is: $elem") + if (arguments.size() > 0) { + arguments.forEachIndexed { index, argument -> + val argExpression = argument.asJsonObject.expr() + var elem = argExpression + if (argExpression.has("elems")) elem = argExpression.elems().getObject(0) + + buildArgs += when { + elem.has("str") -> elem.str() + elem.has("expr") -> breakdownExpr(elem, buildArgs) + elem.has("value") -> "${elem.value()}" + elem.has("lhs") && + elem.has("oper") && + elem.has("rhs") -> breakdownBinaryOperation(elem, buildArgs) + elem.has("name") -> elem.name() + elem.has("recv") -> elem.recv().type().getType() + else -> println("Looks like this element type is: $elem") + } + buildArgs += if (index < arguments.size()) ", " else ")" } - buildArgs += if (index < arguments.size()) ", " else ")" - } + } else buildArgs += ")" return buildArgs } // TODO - look into other types of binary operations private fun breakdownBinaryOperation(expr: JsonObject, buildStmt: String): String { - return if (expr.oper().token() == "DOT") { - "$buildStmt${breakdownExpr(expr.lhs(), buildStmt)}.${breakdownExpr(expr.rhs(), buildStmt)}" - } else { - "Binary Operation has: ${expr.oper().token()}" + val operator = when (expr.oper().token()) { + "DOT" -> "." + "ASSN" -> " = " + else -> expr.oper().token() } + + return "$buildStmt${breakdownExpr(expr.lhs(), buildStmt)}$operator${breakdownExpr(expr.rhs(), buildStmt)}" } /*** @@ -209,35 +242,33 @@ class KParser : Controller() { val listOfMemberType = node.expr().typeArgs() if (listOfMemberType.size() > 0) { - "$type( " + listOfMemberType.getObject(0).ref().pieces().getObject(0).name() + ")" + "$type( " + listOfMemberType.getObject(0).ref().getType() + ")" } else { type } } "HashMap" -> "$type<" + - node.expr().typeArgs().getObject(0).ref() - .pieces().getObject(0).name() + ","+ - node.expr().typeArgs().getObject(1).ref() - .pieces().getObject(0).name() + ">" + node.expr().typeArgs().getObject(0).ref().getType() + ","+ + node.expr().typeArgs().getObject(1).ref().getType() + ">" "ArrayList" -> "$type<" + - node.expr().typeArgs().getObject(0).ref() - .pieces().getObject(0).name() + ">" + node.expr().typeArgs().getObject(0).ref().getType() + ">" "mutableListOf" -> { val listOfMemberType = node.expr().typeArgs() if (listOfMemberType.size() > 0) { - "$type( " + listOfMemberType.getObject(0).ref().pieces().getObject(0).name() + ")" + "$type( " + listOfMemberType.getObject(0).ref().getType() + ")" } else { type } } else -> type } - val valOrVar = if (node.readOnly()) "val " else "var " - return Property(valOrVar, isolatedName, isolatedType) + return Property(valOrVar(node), isolatedName, isolatedType) } + private fun valOrVar(node: JsonObject): String = if (node.readOnly()) "val " else "var " + // For TornadoFX DSLs private fun detectLambdaControls(node: JsonObject, className: String) { val root = node.expr() @@ -274,6 +305,8 @@ class KParser : Controller() { } } + private fun JsonObject.getType() = this.pieces().getObject(0).name() + private fun JsonObject.lambda(): JsonObject = this.get("lambda").asJsonObject private fun JsonObject.expr(): JsonObject = this.get("expr").asJsonObject @@ -298,8 +331,6 @@ class KParser : Controller() { private fun JsonObject.pieces(): JsonArray = this.get("pieces").asJsonArray - private fun JsonObject.name(): String = this.get("name").asString - private fun JsonObject.lhs(): JsonObject = this.get("lhs").asJsonObject private fun JsonObject.rhs(): JsonObject = this.get("rhs").asJsonObject @@ -310,13 +341,23 @@ class KParser : Controller() { private fun JsonObject.decl(): JsonObject = this.get("decl").asJsonObject + private fun JsonObject.oper(): JsonObject = this.get("oper").asJsonObject + + private fun JsonObject.params(): JsonArray = this.get("params").asJsonArray + + private fun JsonObject.recv(): JsonObject = this.get("recv").asJsonObject + + // primitives + + private fun JsonObject.token(): String = this.get("token").asString + private fun JsonObject.readOnly(): Boolean = this.get("readOnly").asBoolean private fun JsonObject.delegated(): Boolean = this.get("delegated").asBoolean - private fun JsonObject.oper(): JsonObject = this.get("oper").asJsonObject + private fun JsonObject.value(): Float = this.get("value").asFloat - private fun JsonObject.token(): String = this.get("token").asString + private fun JsonObject.str(): String = this.get("str").asString - private fun JsonObject.params(): JsonArray = this.get("params").asJsonArray + private fun JsonObject.name(): String = this.get("name").asString } diff --git a/src/main/kotlin/com/github/hd/tornadofxsuite/controller/FXTestGenerator.kt b/src/main/kotlin/com/github/hd/tornadofxsuite/controller/FXTestGenerator.kt index 25da849..898ff5e 100644 --- a/src/main/kotlin/com/github/hd/tornadofxsuite/controller/FXTestGenerator.kt +++ b/src/main/kotlin/com/github/hd/tornadofxsuite/controller/FXTestGenerator.kt @@ -90,7 +90,7 @@ class FXTestGenerator: Controller() { return !fileText.contains("ApplicationTest()") && !fileText.contains("src/test") && !fileText.contains("@Test") - && !fileText.contains("Class Styles") + && !fileText.contains("class Styles") } fun askUserDialog() {