Skip to content

Commit

Permalink
0.7.0 - capture model build warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
carueda committed Dec 13, 2016
1 parent d533194 commit 189304e
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 81 deletions.
3 changes: 3 additions & 0 deletions changelog.md
@@ -1,3 +1,6 @@
2016-12-12 - 0.7.0
- capture model build warnings

2016-12-01 - 0.7.0
- another model revision

Expand Down
50 changes: 29 additions & 21 deletions src/main/scala/tscfg/Main.scala
Expand Up @@ -23,16 +23,16 @@ object Main {
val defaultDestDir: String = "/tmp"

val usage: String = s"""
|tscfg $version
|Usage: tscfg.Main --spec inputFile [options]
|Options (default):
| --pn <packageName> (${defaultGenOpts.packageName})
| --cn <className> (${defaultGenOpts.className})
| --dd <destDir> ($defaultDestDir)
| --j7 generate code for java <= 7 (8)
| --scala generate scala code (java)
| --java generate java code (the default)
|Output is written to $$destDir/$$className.ext
|tscfg $version
|Usage: tscfg.Main --spec inputFile [options]
|Options (default):
| --pn <packageName> (${defaultGenOpts.packageName})
| --cn <className> (${defaultGenOpts.className})
| --dd <destDir> ($defaultDestDir)
| --j7 generate code for java <= 7 (8)
| --scala generate scala code (java)
| --java generate java code (the default)
|Output is written to $$destDir/$$className.ext
""".stripMargin

case class CmdLineOpts(inputFilename: Option[String] = None,
Expand All @@ -41,7 +41,7 @@ object Main {
destDir: String = defaultDestDir,
j7: Boolean = false,
language: String = "java"
)
)

def main(args: Array[String]): Unit = {
generate(getOpts(args.toList))
Expand Down Expand Up @@ -113,9 +113,17 @@ object Main {

println(s"parsing: $inputFilename")
val source = io.Source.fromFile(new File(inputFilename)).mkString.trim
val objectType = ModelBuilder(source)

val buildResult = ModelBuilder(source)
val objectType = buildResult.objectType

//println("\nobjectType:\n |" + objectType.format().replaceAll("\n", "\n |"))

if (buildResult.warnings.nonEmpty) {
println("WARNINGS:")
buildResult.warnings.foreach(w println(s" line ${w.line}: ${w.source}: ${w.message}"))
}

println(s"generating: $destFile")
val pw = out match {
case w: PrintWriter => w
Expand All @@ -137,14 +145,14 @@ object Main {

out.close()

/*
opts.templates foreach { genTemplate =>
val destFile = new File(genTemplate.filename)
printf("%10s: %s\n", genTemplate.what, destFile.getAbsolutePath)
val out = new PrintWriter(destFile)
templateGenerator.generate(genTemplate.what, root, out)
out.close()
}
*/
/*
opts.templates foreach { genTemplate =>
val destFile = new File(genTemplate.filename)
printf("%10s: %s\n", genTemplate.what, destFile.getAbsolutePath)
val out = new PrintWriter(destFile)
templateGenerator.generate(genTemplate.what, root, out)
out.close()
}
*/
}
}
55 changes: 43 additions & 12 deletions src/main/scala/tscfg/ModelBuilder.scala
Expand Up @@ -2,15 +2,45 @@ package tscfg

import com.typesafe.config._
import tscfg.generators.tsConfigUtil
import tscfg.model.{DURATION, ObjectType}
import tscfg.model.DURATION

import scala.collection.JavaConversions._

case class ModelBuildResult(objectType: model.ObjectType,
warnings: List[buildWarnings.Warning])

object buildWarnings {
sealed abstract class Warning(ln: Int,
src: String,
msg: String = "") {
val line: Int = ln
val source: String = src
val message: String = msg
}

case class MultElemListWarning(ln: Int, src: String) extends
Warning(ln, src, "only first element will be considered")

case class OptListElemWarning(ln: Int, src: String) extends
Warning(ln, src, "ignoring optional mark in list's element type")

case class DefaultListElemWarning(ln: Int, default: String, elemType: String) extends
Warning(ln, default, s"ignoring default value='$default' in list's element type: $elemType")
}

class ModelBuilder {
import collection._
import buildWarnings._

def build(conf: Config): ModelBuildResult = {
warns.clear()
ModelBuildResult(objectType = fromConfig(conf),
warnings = warns.toList.sortBy(_.line))
}

def fromConfig(conf: Config): model.ObjectType = {
private val warns = collection.mutable.ArrayBuffer[Warning]()

private def fromConfig(conf: Config): model.ObjectType = {
val memberStructs = getMemberStructs(conf)
val members: immutable.Map[String, model.AnnType] = memberStructs.map { childStruct
val name = childStruct.name
Expand Down Expand Up @@ -116,8 +146,8 @@ class ModelBuilder {
}
}

def toAnnBasicType(valueString: String):
Option[(model.BasicType, Boolean, Option[String])] = {
private def toAnnBasicType(valueString: String):
Option[(model.BasicType, Boolean, Option[String])] = {

val tokens = valueString.split("""\s*\|\s*""")
val typePart = tokens(0).toLowerCase
Expand Down Expand Up @@ -154,7 +184,7 @@ class ModelBuilder {
val line = cv.origin().lineNumber()
val options: ConfigRenderOptions = ConfigRenderOptions.defaults
.setFormatted(false).setComments(false).setOriginComments(false)
println(s"$line: ${cv.render(options)}: WARN: only first element will be considered")
warns += MultElemListWarning(line, cv.render(options))
}

val cv0: ConfigValue = cv.get(0)
Expand All @@ -167,10 +197,10 @@ class ModelBuilder {
toAnnBasicType(valueString) match {
case Some((basicType, isOpt, defaultValue))
if (isOpt)
println(s"WARN: ignoring optional mark in list's element type: $valueString")
warns += OptListElemWarning(cv0.origin().lineNumber(), valueString)

if (defaultValue.isDefined)
println(s"WARN: ignoring default value='${defaultValue.get}' in list's element type: $valueString")
warns += DefaultListElemWarning(cv0.origin().lineNumber(), defaultValue.get, valueString)

basicType

Expand Down Expand Up @@ -213,11 +243,12 @@ class ModelBuilder {

object ModelBuilder {
import java.io.File

import com.typesafe.config.ConfigFactory

def apply(source: String): ObjectType = {
def apply(source: String): ModelBuildResult = {
val config = ConfigFactory.parseString(source).resolve()
new ModelBuilder().fromConfig(config)
new ModelBuilder().build(config)
}

// $COVERAGE-OFF$
Expand All @@ -226,9 +257,9 @@ object ModelBuilder {
val file = new File(filename)
val source = io.Source.fromFile(file).mkString.trim
println("source:\n |" + source.replaceAll("\n", "\n |"))
val objectType = ModelBuilder(source)
println(s"objectType:")
println(model.util.format(objectType))
val result = ModelBuilder(source)
println("objectType:")
println(model.util.format(result.objectType))
}
// $COVERAGE-ON$
}
28 changes: 17 additions & 11 deletions src/main/scala/tscfg/generators/java/JavaGen.scala
Expand Up @@ -112,8 +112,8 @@ class JavaGen(genOpts: GenOpts) extends Generator(genOpts) {
}

private def generateForList(lt: ListType,
classNamePrefixOpt: Option[String],
className: String): Res = {
classNamePrefixOpt: Option[String],
className: String): Res = {
val className2 = className + (if (className.endsWith("$Elm")) "" else "$Elm")
val elem = generate(lt.t, classNamePrefixOpt, className2)
val elemRefType = toObjectType(elem.javaType)
Expand Down Expand Up @@ -208,9 +208,9 @@ class JavaGen(genOpts: GenOpts) extends Generator(genOpts) {
}

private def listMethodName(javaType: ListJavaType, lt: ListType, path: String)
(implicit listAccessors: collection.mutable.Map[String, String],
methodNames: MethodNames
): String = {
(implicit listAccessors: collection.mutable.Map[String, String],
methodNames: MethodNames
): String = {

val (_, methodName) = rec(javaType, lt, "")
methodName + s"""(c.getList("$path"))"""
Expand Down Expand Up @@ -260,7 +260,7 @@ class JavaGen(genOpts: GenOpts) extends Generator(genOpts) {
}

private def listMethodDefinition(elemMethodName: String, javaType: JavaType)
(implicit methodNames: MethodNames): (String, String) = {
(implicit methodNames: MethodNames): (String, String) = {

val elem = if (elemMethodName.startsWith(methodNames.listPrefix))
s"$elemMethodName((com.typesafe.config.ConfigList)cv)"
Expand Down Expand Up @@ -293,10 +293,10 @@ object JavaGen {
// $COVERAGE-OFF$
def generate(filename: String, showOut: Boolean = false): GenResult = {
val file = new File(filename)
val src = io.Source.fromFile(file).mkString.trim
val source = io.Source.fromFile(file).mkString.trim

if (showOut)
println("src:\n |" + src.replaceAll("\n", "\n |"))
println("source:\n |" + source.replaceAll("\n", "\n |"))

val className = "Java" + {
val noPath = filename.substring(filename.lastIndexOf('/') + 1)
Expand All @@ -305,9 +305,15 @@ object JavaGen {
util.upperFirst(symbol) + "Cfg"
}

val objectType = ModelBuilder(src)
if (showOut)
println("\nobjSpec:\n |" + model.util.format(objectType).replaceAll("\n", "\n |"))
val buildResult = ModelBuilder(source)
val objectType = buildResult.objectType
if (showOut) {
println("\nobjectType:\n |" + model.util.format(objectType).replaceAll("\n", "\n |"))
if (buildResult.warnings.nonEmpty) {
println("warnings:")
buildResult.warnings.foreach(w println(s" line ${w.line}: ${w.source}: ${w.message}"))
}
}

val genOpts = GenOpts("tscfg.example", className, j7 = false)

Expand Down
14 changes: 10 additions & 4 deletions src/main/scala/tscfg/generators/scala/ScalaGen.scala
Expand Up @@ -161,7 +161,7 @@ object ScalaGen {
val source = io.Source.fromFile(file).mkString.trim

if (showOut)
println("src:\n |" + source.replaceAll("\n", "\n |"))
println("source:\n |" + source.replaceAll("\n", "\n |"))

val className = "Scala" + {
val noPath = filename.substring(filename.lastIndexOf('/') + 1)
Expand All @@ -170,9 +170,15 @@ object ScalaGen {
util.upperFirst(symbol) + "Cfg"
}

val objectType = ModelBuilder(source)
if (showOut)
println("\nobjSpec:\n |" + model.util.format(objectType).replaceAll("\n", "\n |"))
val buildResult = ModelBuilder(source)
val objectType = buildResult.objectType
if (showOut) {
println("\nobjectType:\n |" + model.util.format(objectType).replaceAll("\n", "\n |"))
if (buildResult.warnings.nonEmpty) {
println("warnings:")
buildResult.warnings.foreach(w println(s" line ${w.line}: ${w.source}: ${w.message}"))
}
}

val genOpts = GenOpts("tscfg.example", className, j7 = false)

Expand Down

0 comments on commit 189304e

Please sign in to comment.