Skip to content

Commit

Permalink
Parser update for 6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Karasiq committed Oct 28, 2018
1 parent cf31437 commit 84386df
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 35 deletions.
@@ -1,8 +1,9 @@
package com.karasiq.highcharts.generator.writers

import org.apache.commons.lang3.StringEscapeUtils

import com.karasiq.highcharts.generator.ConfigurationObject
import com.karasiq.highcharts.generator.ast.{ScalaJsClass, ScalaJsDefinition, ScalaJsMethod, ScalaJsValue}
import org.apache.commons.lang3.StringEscapeUtils

object ScalaClassWriter {
// Scala keywords
Expand All @@ -22,7 +23,7 @@ class ScalaClassWriter extends ClassWriter {

private val compoundValueName = "(\\w+)<(\\w+)>".r

override def writeClass(scalaClass: ScalaJsClass)(writer: (String) Unit): Unit = scalaClass match {
override def writeClass(scalaClass: ScalaJsClass)(writer: String Unit): Unit = scalaClass match {
case ScalaJsClass(jsName, className, definitions)
writer(
s"""/**
Expand All @@ -35,10 +36,10 @@ class ScalaClassWriter extends ClassWriter {

if (isTrait) {
writer("@js.native")
writer(s"trait ${validScalaName(className)} extends js.Object {")
writer(s"trait ${validScalaName(className)} extends com.highcharts.HighchartsGenericObject {")
} else {
writer("@js.annotation.ScalaJSDefined")
writer(s"class ${validScalaName(className)} extends js.Object {")
writer(s"class ${validScalaName(className)} extends com.highcharts.HighchartsGenericObject {")
}

val tab = " " // Tabulation
Expand All @@ -54,7 +55,8 @@ class ScalaClassWriter extends ClassWriter {
writer(tab + s"val $scalaName: $scalaType = js.native")
} else value match {
case Some(v)
writer(tab + s"val $scalaName: $scalaType = $v")
// writer(tab + s"val $scalaName: $scalaType = $v")
writer(tab + s"val $scalaName: js.UndefOr[$scalaType] = $v")

case None if scalaType == "js.Any"
writer(tab + s"val $scalaName: $scalaType = js.undefined")
Expand Down Expand Up @@ -116,7 +118,8 @@ class ScalaClassWriter extends ClassWriter {

val args = parameters.collect {
case ScalaJsValue(_, argName, argType, Some(argValue))
s"${validScalaName(argName)}: $argType = $argValue"
// s"${validScalaName(argName)}: $argType = $argValue"
s"${validScalaName(argName)}: js.UndefOr[$argType] = $argValue"

case ScalaJsValue(_, argName, argType, None)
s"${validScalaName(argName)}: js.UndefOr[$argType] = js.undefined"
Expand All @@ -125,17 +128,17 @@ class ScalaClassWriter extends ClassWriter {
for (ScalaJsValue(_, scalaName, scalaType, value) <- parameters) {
val outer = validScalaName(scalaName + "Outer")
val name = validScalaName(scalaName)
val tpe = if (value.isDefined || scalaType == "js.Any") scalaType else s"js.UndefOr[$scalaType]"
val tpe = if (/* value.isDefined ||*/ scalaType == "js.Any") scalaType else s"js.UndefOr[$scalaType]"
writer(tab + tab + s"val $outer: $tpe = $name")
}
writer(tab + tab + s"new ${validScalaName(scalaClass.scalaName)} {")
writer(tab + tab + s"com.highcharts.HighchartsGenericObject.toCleanObject(new ${validScalaName(scalaClass.scalaName)} {")
for (ScalaJsValue(_, scalaName, scalaType, value) <- parameters) {
val name = validScalaName(scalaName)
val outer = validScalaName(scalaName + "Outer")
val tpe = if (value.isDefined || scalaType == "js.Any") scalaType else s"js.UndefOr[$scalaType]"
val tpe = if (/*value.isDefined || */ scalaType == "js.Any") scalaType else s"js.UndefOr[$scalaType]"
writer(tab + tab + tab + s"override val $name: $tpe = $outer")
}
writer(tab + tab + "}")
writer(tab + tab + "})")
writer(tab + "}")
writer("}")
}
Expand Down
Expand Up @@ -38,6 +38,24 @@ object ScalaJsClassBuilder {

class ScalaJsClassBuilder {
private def scalaType(classes: Set[String], tpe: Option[String], selfClass: Option[String] = None): Option[String] = {

object Prefixed {
def unapplySeq(s: String): Option[Seq[String]] = {
Some(s.split('.'))
}
}

object Union {
def unapplySeq(t: String): Option[Seq[String]] = {
val t1 = if (t.startsWith("(") && t.endsWith(")")) t.drop(1).dropRight(1) else t
val tokens: Array[String] = t1.split('|')
.map(_.trim)
.filter(_.nonEmpty)

if (tokens.length > 1) Some(tokens.toSeq) else None
}
}

// val array = """^Array\.<(.+?)>$""".r
object TypedArray {
def unapply(str: String): Option[String] = {
Expand All @@ -63,27 +81,33 @@ class ScalaJsClassBuilder {
}

def stdTypes: PartialFunction[String, String] = selfTypeObject.orElse {
case "Color"
case "Color" | "color" | Prefixed("Highcharts", "ColorString")
"String | js.Object"

case "String"
case "String" | "string"
"String"

case "Function" | "function"
"js.Function"

case "CSSObject" | "Object"
case "CSSObject" | "Object" | "object" | Prefixed("Highcharts", "CSSObject" | "SVGAttributes" | "AnimationOptionsObject")
"js.Object"

case "Number"
case Prefixed("Highcharts", "Dictionary") | Prefixed("Highcharts", "Dictionary", _)
"js.Object"

case "Number" | "number"
"Double"

case "Boolean"
case "Boolean" | "boolean"
"Boolean"

case "Mixed"
case "Mixed" | "*"
"js.Any"

case "null"
"Null"

case TypedArray(t)
// println("Array " + t)
val tpe: String = if (stdTypes.isDefinedAt(t)) {
Expand All @@ -95,17 +119,16 @@ class ScalaJsClassBuilder {
}
s"js.Array[$tpe]"

case "Array"
case "Array" | "array"
"js.Array[js.Any]"

case t if t.contains("|") // Union type
val t1 = if (t.startsWith("(") && t.endsWith(")")) t.drop(1).dropRight(1) else t
val tokens: Array[String] = t1.split("\\|")
.map(_.trim)
.filter(_.nonEmpty)
.collect(stdTypes)
case Union(tokens @ _*) // Union type
val recognized = tokens.collect(stdTypes)
// println(t + " " + tokens.toList)
ScalaJsClassBuilder.unionType(tokens.toList)
ScalaJsClassBuilder.unionType(recognized.toList)

// case Prefixed("Highcharts", t) if classes.contains(ScalaJsClassBuilder.classNameFor(t)) ⇒
// s"CleanJsObject[${ScalaJsClassBuilder.classNameFor(t)}]"

case t if t.nonEmpty && classes.contains(ScalaJsClassBuilder.classNameFor(t))
s"CleanJsObject[${ScalaJsClassBuilder.classNameFor(t)}]"
Expand Down Expand Up @@ -139,7 +162,7 @@ class ScalaJsClassBuilder {
if (value.trim == "null") {
// Null value
s"null.asInstanceOf[$scalaType]"
} else if (cfg.returnType.exists(_.contains("String")) || scalaType == "String") {
} else if (cfg.returnType.exists(_.toLowerCase.contains("string")) || scalaType == "String") {
// String literal
ScalaJsClassBuilder.escapeString(value)
} else {
Expand Down Expand Up @@ -173,12 +196,17 @@ class ScalaJsClassBuilder {
} */

// Extract `type` field
val defaultValue = if (cfg.title.contains("type") && cfg.returnType.contains("String") && cfg.defaults.isEmpty) {
val compoundValueName = "(\\w+)<(\\w+)>".r
cfg.parent.collect {
case compoundValueName(baseName, typeArg)
wrapString(typeArg)
}
def isTypeField =
cfg.title.contains("type") &&
cfg.returnType.map(_.toLowerCase).contains("string")

val defaultValue = if (isTypeField) {
cfg.defaults
.map(wrapString)
.orElse {
val CompoundValueName = "(\\w+)<(\\w+)>".r
cfg.parent.collect { case CompoundValueName(_, typeArg) wrapString(typeArg) }
}
} else {
None
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/com/highcharts/AnySeriesDef.scala
Expand Up @@ -6,7 +6,7 @@ import scala.scalajs.js
trait AnySeriesDef {
type AnySeries

type SeriesCfg = js.UndefOr[js.Array[CleanJsObject[AnySeries]]]
type SeriesCfg = js.UndefOr[js.Array[js.Any]]

implicit def anySeriesArrayConvert(arr: js.Array[AnySeries]): SeriesCfg = {
arr.map(obj CleanJsObject(obj.asInstanceOf[js.Object])).asInstanceOf[SeriesCfg]
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/com/highcharts/CleanJsObject.scala
Expand Up @@ -13,6 +13,9 @@ object CleanJsObject {
case und if js.isUndefined(und)
js.undefined.asInstanceOf[js.Object]

case array if js.Array.isArray(array) // Pass arrays
array

case obj
val newObj: js.Object = new js.Object()

Expand Down
15 changes: 15 additions & 0 deletions src/main/scala/com/highcharts/HighchartsGenericObject.scala
@@ -0,0 +1,15 @@
package com.highcharts

import scala.scalajs.js.annotation.ScalaJSDefined

/**
* Generic highcharts object
*/
@ScalaJSDefined
trait HighchartsGenericObject extends scalajs.js.Object

object HighchartsGenericObject {
def toCleanObject[T <: HighchartsGenericObject](obj: T): CleanJsObject[T] = {
CleanJsObject(obj).asInstanceOf[CleanJsObject[T]]
}
}
18 changes: 15 additions & 3 deletions src/main/scala/com/highcharts/HighchartsImplicits.scala
@@ -1,16 +1,28 @@
package com.highcharts

import com.highcharts.HighchartsAliases.SeriesCfgData

import scala.language.implicitConversions
import scala.scalajs.js
import scala.scalajs.js.{UndefOr, `|`}
import scala.scalajs.js.{`|`, UndefOr}

import com.highcharts.HighchartsAliases.SeriesCfgData

trait HighchartsImplicits {
type Cfg[T <: js.Object] = UndefOr[CleanJsObject[T]]

type CfgArray[T <: js.Object] = UndefOr[js.Array[CleanJsObject[T]]]

implicit def highchartsGenericObjectToJSAny[T](value: T)(implicit ev: T HighchartsGenericObject): js.Any = {
HighchartsGenericObject.toCleanObject(ev(value)).asInstanceOf[js.Any]
}

implicit def highchartsUnionArray[V, U1, U2](obj: js.Array[V])(implicit ev: js.`|`.Evidence[V, U1 | U2]): js.Array[U1 | U2] = {
obj.asInstanceOf[js.Array[U1 | U2]]
}

implicit def highchartsUndefOrUnionArray[V, U1, U2](obj: js.Array[V])(implicit ev: js.`|`.Evidence[V, U1 | U2]): js.UndefOr[js.Array[U1 | U2]] = {
obj.asInstanceOf[js.Array[U1 | U2]]
}

implicit def highchartsUnionCleanObject[V <: js.Object, U1, U2](obj: V)(implicit ev: js.`|`.Evidence[CleanJsObject[V], U1 | U2]): U1 | U2 = {
CleanJsObject(obj).asInstanceOf[U1 | U2]
}
Expand Down

0 comments on commit 84386df

Please sign in to comment.