From de85b8e746f5d16bda895ff86e862b17c7e313da Mon Sep 17 00:00:00 2001 From: Amanda Hinchman-Dominguez Date: Sun, 6 Jan 2019 20:48:48 -0600 Subject: [PATCH] fixed several bugs for the AST parser. Will need to figure out why the console is only outputting controls for just one view class and will need to start mapping relationships of nodes. --- sample_AST_breakdown.txt | 88 +++++++++++++ .../kotlin/com/github/ast/parser/KParser.kt | 123 ++++++++++++------ .../controller/FXTestGenerator.kt | 2 +- 3 files changed, 171 insertions(+), 42 deletions(-) create mode 100644 sample_AST_breakdown.txt 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() {