diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 55ebdce..a11093d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -60,7 +60,7 @@ jobs:
run: sbt ++${{ matrix.scala }} scripted
- name: Compress target directories
- run: tar cf targets.tar sbt/target target meta/docs/target cli/target core/target example/target project/target
+ run: tar cf targets.tar sbt/target meta/integration-tests/target target meta/docs/target cli/target core/target example/target project/target
- name: Upload target directories
uses: actions/upload-artifact@v2
diff --git a/README.md b/README.md
index b5ef96f..c95e383 100644
--- a/README.md
+++ b/README.md
@@ -98,123 +98,6 @@ The pattern supports two wildcards:
The --dir, --jar, and --url options specify the directories and JAR files that are used when locating SemanticDB files.
Each of these can be provided multiple times.
-By default, the classpath that was used when executing Scala2PlantUML is also used.
-
- -d, --dir
Directories of the SemanticDB target roots containing META-INF/semanticdb/**/*.semanticdb files.
-
- Example:
- --dir 'my-project/target/scala-2.13/meta'
-
- -j, --jar JAR containing META-INF/semanticdb/**/*.semanticdb files.
-
- Example:
- --jar 'foo.jar'
-
- -u, --url A URL to a JAR containing META-INF/semanticdb/**/*.semanticdb files.
-
- Example:
- --url 'https://repo1.maven.org/maven2/com/example/foo/foo_2.13/1.0.0/foo_2.13-1.0.0-semanticdb.jar'
-
-The --project and --source options specify where within the search locations the SemanticDB files can be found.
-Each of these can be provided multiple times. The result will be all combinations of projects and source roots.
-
- -p, --project The name of the projects that have SemanticDB files.
-
- The project name will be used when looking for SemanticDB files such as:
- META-INF/semanticdb///*.semanticdb
-
- An empty project name will search in:
- META-INF/semanticdb//*.semanticdb
-
- Default: ''
-
- Example:
- --project my-project
-
- -s, --source The directory relative to the project where the source files were located.
-
- The source will be used when looking for SemanticDB files such as
- META-INF/semanticdb///*.semanticdb.
-
- Default: src/main/scala
-
- Example:
- --source 'source/scala'
-
- -l, --max-level The maximum number of levels that will be traversed when following symbol references.
-
- This means that parent symbols that would be beyond the max level will not be shown.
-
- A diagram with a max-level of 1 will only contain the initial symbol.
-
- Default: Unlimited
-
- Example:
- --max-level 3
-
- -o, --output Write the output to the given file.
-
- Example:
- --output docs/diagrams/my-project.puml
-
- -c, --colour Enables coloured output.
-
- Default: true
-
- Example:
- --colour false
-
- -v, --verbose Increases the log level.
-
- This can be provided twice for the most verbose logging.
-
- Example:
- -vv
-
- -h, --help
- --version
-Error: Missing argument symbol
-Scala2PlantUML version 0.2.0
-Usage: scala2plantuml [options] symbol
-
-Scala2PlantUML generates PlantUML Class Diagrams from Scala SemanticDB files.
-
- symbol The symbol to use as the starting point for generating the diagram.
-
- To get a symbol from a class name, convert the package name separate '.' to '/' and add a '#'
- suffix. For an object use a suffix of '.'.
-
- See https://scalameta.org/docs/semanticdb/specification.html#symbol-1 for the full syntax.
-
- Examples:
- 'com/example/Foo#' (class com.example.Foo)
- 'com/example/Foo.' (object com.example.Foo)
- 'com/example/Foo.bar.' (value/variable bar on object com.example.Foo)
- 'com/example/Foo#baz().' (function baz on class com.example.Foo)
-
-The --include and --exclude options control which symbols will be processed. Each of these can be provided multiple times.
-
-The pattern supports two wildcards:
-1) ** (matches any character)
-2) * (matches all characters except for '/')
-
- -i, --include Only include symbols that match the pattern.
-
- Default: '**'
-
- Example:
- --include 'com/example/**/model/*'
-
- -e, --exclude Excludes all symbols that match the pattern.
-
- Default: 'scala/**', 'java/**'
-
- Example:
- --exclude 'com/example/**/data/*'
-
-The --dir, --jar, and --url options specify the directories and JAR files that are used when locating SemanticDB files.
-Each of these can be provided multiple times.
-
By default, the classpath that was used when executing Scala2PlantUML is also used.
-d, --dir Directories of the SemanticDB target roots containing META-INF/semanticdb/**/*.semanticdb files.
diff --git a/build.sbt b/build.sbt
index 6908ee2..ef9f674 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,3 +1,5 @@
+import com.typesafe.tools.mima.core._
+
val scala212 = "2.12.13"
val scala213 = "2.13.4"
val supportedScalaVersions = List(scala212, scala213)
@@ -75,7 +77,7 @@ inThisBuild(
)
),
githubWorkflowPublishTargetBranches := List(RefPredicate.StartsWith(Ref.Tag("v"))),
- githubWorkflowTargetTags ++= Seq("v*"),
+ githubWorkflowTargetTags ++= List("v*"),
pgpSigningKey := Some("0x8DB7DFA142551359!"),
// This needs to be set otherwise the GitHub workflow plugin gets confused about which
// version to use for the publish job.
@@ -87,6 +89,9 @@ inThisBuild(
val commonProjectSettings = List(
isScala213 := isScala213Setting.value,
+ // Who cares about these. Forwards binary compatibility is used as an approximation for source
+ // backwards compatibility and missing classes isn't a problem.
+ mimaForwardIssueFilters += "0.2.0" -> List(ProblemFilters.exclude[MissingClassProblem]("nz.co.bottech.scala2plantuml.*")),
name := s"${(LocalRootProject / name).value}-${name.value}",
scalastyleFailOnError := true,
scalastyleFailOnWarning := true,
@@ -109,7 +114,7 @@ val metaProjectSettings = List(
)
lazy val root = (project in file("."))
- .aggregate(cli, core, docs, example, sbtProject)
+ .aggregate(cli, core, docs, example, integrationTests, sbtProject)
.settings(metaProjectSettings)
.settings(
crossScalaVersions := supportedScalaVersions,
@@ -156,6 +161,18 @@ lazy val cli = project
)
)
+// Use a separate project rather than a configuration to get IntelliJ support.
+lazy val integrationTests = (project in (file("meta") / "integration-tests"))
+ .settings(metaProjectSettings)
+ .settings(
+ libraryDependencies ++= List(
+ "com.lihaoyi" %% "utest" % utestVersion % Test
+ ),
+ testFrameworks += new TestFramework("utest.runner.Framework"),
+ Test / fork := true,
+ Test / javaOptions += s"-Dit.classpath=${(cli / Compile / fullClasspathAsJars).value.map(_.data).mkString(":")}"
+ )
+
lazy val sbtProject = (project in file("sbt"))
.dependsOn(core)
.enablePlugins(SbtPlugin)
@@ -191,7 +208,7 @@ lazy val sbtProject = (project in file("sbt"))
scriptedLaunchOpts += s"-Dplugin.version=${version.value}"
)
-lazy val docs = (project in file("meta/docs"))
+lazy val docs = (project in (file("meta") / "docs"))
// Include build info here so that we can override the version.
.enablePlugins(BuildInfoPlugin, MdocPlugin)
.dependsOn(cli)
diff --git a/cli/src/main/scala/nz/co/bottech/scala2plantuml/ConfigParser.scala b/cli/src/main/scala/nz/co/bottech/scala2plantuml/ConfigParser.scala
index 8903ccb..8d9f9bb 100644
--- a/cli/src/main/scala/nz/co/bottech/scala2plantuml/ConfigParser.scala
+++ b/cli/src/main/scala/nz/co/bottech/scala2plantuml/ConfigParser.scala
@@ -1,19 +1,24 @@
package nz.co.bottech.scala2plantuml
-import scopt.{DefaultOEffectSetup, DefaultOParserSetup, OEffectSetup, OParser, OParserSetup}
+import scopt._
import java.io.File
object ConfigParser {
+ final private object Terminated extends RuntimeException
+
private val parserSetup: OParserSetup = new DefaultOParserSetup {
override def showUsageOnError: Option[Boolean] = Some(true)
}
private val effectSetup: OEffectSetup = new DefaultOEffectSetup {
+
// Don't exit otherwise sbt traps this and there are confusing errors.
// This is especially troublesome when running this from mdoc.
- override def terminate(exitState: Either[String, Unit]): Unit = ()
+ @SuppressWarnings(Array("org.wartremover.warts.Throw"))
+ override def terminate(exitState: Either[String, Unit]): Unit =
+ throw Terminated
}
// scalastyle:off method.length
@@ -218,7 +223,10 @@ object ConfigParser {
// scalastyle:on method.length
def parse(args: Array[String]): Option[Config] =
- OParser.parse(parser, args, Config(), parserSetup, effectSetup)
+ try OParser.parse(parser, args, Config(), parserSetup, effectSetup)
+ catch {
+ case Terminated => None
+ }
private def validateConfig(config: Config): Either[String, Unit] =
if (config.ignore(config.symbol)) Left("Symbol must match include patterns and not match exclude patterns.")
diff --git a/meta/integration-tests/src/test/scala/nz/co/bottech/scala2plantuml/cli/CLIItTests.scala b/meta/integration-tests/src/test/scala/nz/co/bottech/scala2plantuml/cli/CLIItTests.scala
new file mode 100644
index 0000000..f00051e
--- /dev/null
+++ b/meta/integration-tests/src/test/scala/nz/co/bottech/scala2plantuml/cli/CLIItTests.scala
@@ -0,0 +1,17 @@
+package nz.co.bottech.scala2plantuml.cli
+
+import utest._
+
+import scala.sys.process._
+
+object CLIItTests extends TestSuite {
+
+ private val classpath = Option(System.getProperty("it.classpath")).get
+
+ val tests: Tests = Tests {
+ test("show help") {
+ val exitCode = List("java", "-classpath", classpath, "nz.co.bottech.scala2plantuml.Scala2PlantUML").!
+ assert(exitCode == 0)
+ }
+ }
+}