Skip to content

Commit

Permalink
Merge branch '1.x' into 2.x to support Scala 2.13 and merge improveme…
Browse files Browse the repository at this point in the history
…nts in the constrained module
  • Loading branch information
Peter Empen committed Apr 1, 2020
2 parents 670679e + 8f8811e commit f63e8f6
Show file tree
Hide file tree
Showing 134 changed files with 4,782 additions and 2,524 deletions.
1 change: 1 addition & 0 deletions .scalafmt.conf
Expand Up @@ -14,3 +14,4 @@ newlines {
optIn.breakChainOnFirstMethodDot = false
rewrite.rules = [PreferCurlyFors, RedundantBraces, RedundantParens, SortModifiers, SortImports]
## verticalMultiline.atDefnSite = true
project.excludeFilters = [".*/scala/collection/mutable/ExtHashSet.scala"]
11 changes: 7 additions & 4 deletions .travis.yml
@@ -1,8 +1,11 @@
language: scala
scala:
- 2.11.11
- 2.12.7
- 2.13.1
- 2.12.10
jdk:
- oraclejdk8
- oraclejdk11
script:
- sbt test scalafmtCheck test:scalafmtCheck scalafmtSbtCheck
- sbt +test scalafmtCheck test:scalafmtCheck scalafmtSbtCheck
cache:
directories:
- $HOME/.ivy2/cache
56 changes: 38 additions & 18 deletions build.sbt
Expand Up @@ -19,9 +19,25 @@ lazy val core = project
name := "Graph Core",
version := Version.core,
libraryDependencies ++= Seq(
"org.scalacheck" %% "scalacheck" % "1.13.4" % "optional;provided",
"org.scalacheck" %% "scalacheck" % "1.14.0" % "optional;provided",
"org.gephi" % "gephi-toolkit" % "0.9.2" % "test" classifier "all"
)
),
dependencyOverrides ++= {
val release = "RELEASE90"
def netbeansModule(module: String) = "org.netbeans.modules" % module % release
def netbeansApi(module: String) = "org.netbeans.api" % module % release
Seq(
netbeansModule("org-netbeans-core"),
netbeansModule("org-netbeans-core-startup-base"),
netbeansModule("org-netbeans-modules-masterfs"),
netbeansApi("org-openide-util-lookup"),
netbeansApi("org-openide-filesystems"),
netbeansApi("org-openide-util-ui"),
netbeansApi("org-openide-dialogs"),
netbeansApi("org-openide-nodes"),
netbeansApi("org-netbeans-api-annotations-common")
)
}
)
)

Expand All @@ -39,7 +55,10 @@ lazy val dot = project
.in(file("dot"))
.dependsOn(core)
.settings(
defaultSettings ++ Seq(name := "Graph DOT", version := Version.dot)
defaultSettings ++ Seq(
name := "Graph DOT",
version := Version.dot
)
)

lazy val json = project
Expand All @@ -49,7 +68,7 @@ lazy val json = project
defaultSettings ++ Seq(
name := "Graph JSON",
version := Version.json,
libraryDependencies += "net.liftweb" %% "lift-json" % "3.0.1"
libraryDependencies += "net.liftweb" %% "lift-json" % "3.4.0"
)
)

Expand All @@ -59,37 +78,38 @@ lazy val misc = project
.settings(
defaultSettings ++ Seq(
name := "Graph Miscellaneous",
version := Version.misc
version := "unpublished"
)
)

ThisBuild / scalafmtConfig := Some(file(".scalafmt.conf"))

ThisBuild / resolvers ++= Seq(
"NetBeans" at "http://bits.netbeans.org/nexus/content/groups/netbeans/",
("NetBeans" at "http://bits.netbeans.org/nexus/content/groups/netbeans/").withAllowInsecureProtocol(true),
"gephi-thirdparty" at "https://raw.github.com/gephi/gephi/mvn-thirdparty-repo/"
)

ThisBuild / scalafmtConfig := Some(file(".scalafmt.conf"))

val unusedImports = "-Ywarn-unused:imports"
lazy val defaultSettings = Defaults.coreDefaultSettings ++ Seq(
scalaVersion := Version.compiler_2_12,
crossScalaVersions := Seq(scalaVersion.value, Version.compiler_2_11),
scalaVersion := Version.compiler_2_13,
crossScalaVersions := Seq(Version.compiler_2_12, scalaVersion.value),
organization := "org.scala-graph",
scalacOptions ++= Seq(
unusedImports,
"-Yrangepos",
"-Ywarn-unused:privates"
),
Compile / console / scalacOptions := (Compile / scalacOptions).value filterNot (_ eq unusedImports),
addCompilerPlugin(scalafixSemanticdb),
Test / parallelExecution := false,
Compile / doc / scalacOptions ++=
Opts.doc.title(name.value) ++
Opts.doc.version(version.value),
// prevents sbteclipse from including java source directories
Compile / unmanagedSourceDirectories := (Compile / scalaSource)(Seq(_)).value,
Test / unmanagedSourceDirectories := (Test / scalaSource)(Seq(_)).value,
Compile / doc / scalacOptions ++= List("-diagrams", "-implicits"),
Compile / doc / scalacOptions ++= (baseDirectory map { d =>
Seq("-doc-root-content", (d / "rootdoc.txt").getPath)
}).value,
autoAPIMappings := true,
Test / testOptions := Seq(Tests.Filter(s => s.endsWith("Test"))),
libraryDependencies ++= Seq(
"junit" % "junit" % "4.12" % "test",
"org.scalatest" %% "scalatest" % "3.0.1" % "test",
"org.scala-lang.modules" %% "scala-xml" % "1.0.5" % "test"
)
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
) ++ GraphSonatype.settings
@@ -0,0 +1,174 @@
package scalax.collection.constrained

import scalax.collection.GraphPredef.{EdgeLikeIn, InParam, InnerEdgeParam, InnerNodeParam, OutParam, OuterEdge, OuterNode, Param}
import scalax.collection.config._
import scalax.collection.constrained.config.GenConstrainedConfig
import scalax.collection.constrained.generic.GraphConstrainedCompanion
import scalax.collection.{GraphLike => SimpleGraphLike}

import scala.annotation.unchecked.{uncheckedVariance => uV}
import scala.collection.{GenTraversableOnce, Set}
import scala.language.postfixOps

/** A template trait for graphs.
*
* This trait provides the common structure and operations of immutable graphs independently
* of its representation.
*
* If `E` inherits `DirectedEdgeLike` the graph is directed, otherwise it is undirected or mixed.
*
* @tparam N the user type of the nodes (vertices) in this graph.
* @tparam E the higher kinded type of the edges (links) in this graph.
* @tparam This the higher kinded type of the graph itself.
* @author Peter Empen
*/
trait GraphLike[N,
E[+X] <: EdgeLikeIn[X],
+This[X, Y[+X] <: EdgeLikeIn[X]] <: GraphLike[X, Y, This] with Set[Param[X, Y]] with Graph[X, Y]]
extends SimpleGraphLike[N, E, This]
with GraphOps[N, E, This]
with Constrained[N, E, This[N, E]] {
this: // This[N,E] => see https://youtrack.jetbrains.com/issue/SCL-13199
This[N, E] with GraphLike[N, E, This] with Set[Param[N, E]] with Graph[N, E] =>

override val graphCompanion: GraphConstrainedCompanion[This]
protected type Config <: GraphConfig with GenConstrainedConfig

val constraintFactory: ConstraintCompanion[Constraint]
override def stringPrefix: String = constraintFactory.stringPrefix getOrElse super.stringPrefix

override protected def plusPlus(newNodes: Iterable[N], newEdges: Iterable[E[N]]): This[N, E] =
graphCompanion.fromWithoutCheck[N, E](nodes.toOuter ++ newNodes, edges.toOuter ++ newEdges)(edgeT, config)

override protected def minusMinus(delNodes: Iterable[N], delEdges: Iterable[E[N]]): This[N, E] = {
val delNodesEdges = minusMinusNodesEdges(delNodes, delEdges)
graphCompanion.fromWithoutCheck[N, E](delNodesEdges._1, delNodesEdges._2)(edgeT, config)
}

@transient private var suspended = false
protected def checkSuspended: Boolean = suspended
final protected def withoutChecks[R](exec: => R): R = {
val old = suspended
suspended = true
val res = exec
suspended = old
res
}

import PreCheckFollowUp._

def +?(elem: Param[N, E]): Either[ConstraintViolation, This[N, E]] = elem match {
case in: InParam[N, E] =>
in match {
case n: OuterNode[N] => this +? n.value
case e: OuterEdge[N, E] => this +#? e.edge
}
case out: OutParam[_, _] =>
out match {
case n: InnerNodeParam[N] => this +? n.value
case e: InnerEdgeParam[N, E, _, E] => this +#? e.asEdgeT[N, E, this.type](this).toOuter
}
}

protected def +#?(e: E[N]): Either[ConstraintViolation, This[N, E]]

def ++?(elems: GenTraversableOnce[Param[N, E]]): Either[ConstraintViolation, This[N, E]] = {
val (outerNodes, outerEdges, preCheckResult) = {
val it = elems match {
case x: Iterable[Param[N, E]] => x
case x: TraversableOnce[Param[N, E]] => x.toIterable
case _ => throw new IllegalArgumentException("TraversableOnce expected.")
}
val p = new Param.Partitions[N, E](it filter (elm => !(this contains elm)))
(p.toOuterNodes, p.toOuterEdges, preAdd(p.toInParams.toSet.toSeq: _*))
}
preCheckResult.followUp match {
case Complete => Right(plusPlus(outerNodes, outerEdges))
case PostCheck => postAdd(plusPlus(outerNodes, outerEdges), outerNodes, outerEdges, preCheckResult)
case Abort => Left(preCheckResult)
}
}

def -?(elem: Param[N, E]): Either[ConstraintViolation, This[N, E]] = elem match {
case in: InParam[N, E] =>
in match {
case n: OuterNode[N] => this -? n.value
case e: OuterEdge[N, E] => this -#? e.edge
}
case out: OutParam[_, _] =>
out match {
case n: InnerNodeParam[N] => this -? n.value
case e: InnerEdgeParam[N, E, _, E] => this -#? e.asEdgeT[N, E, this.type](this).toOuter
}
}

protected def -#?(e: E[N]): Either[ConstraintViolation, This[N, E]]

def --?(elems: GenTraversableOnce[Param[N, E]]): Either[ConstraintViolation, This[N, E]] = {
lazy val p = partition(elems.to[scalax.collection.IterableOnce])
lazy val (outerNodes, outerEdges) = (p.toOuterNodes.toSet, p.toOuterEdges.toSet)
def innerNodes =
(outerNodes.view map (this find _) filter (_.isDefined) map (_.get) force).toSet
def innerEdges =
(outerEdges.view map (this find _) filter (_.isDefined) map (_.get) force).toSet

type C_NodeT = self.NodeT
type C_EdgeT = self.EdgeT
val preCheckResult = preSubtract(innerNodes.asInstanceOf[Set[C_NodeT]], innerEdges.asInstanceOf[Set[C_EdgeT]], true)
preCheckResult.followUp match {
case Complete => Right(minusMinus(outerNodes, outerEdges))
case PostCheck =>
postSubtract(minusMinus(outerNodes, outerEdges), outerNodes, outerEdges, preCheckResult)
case Abort => Left(preCheckResult)
}
}

protected def checkedPlus(contained: => Boolean,
preAdd: => PreCheckResult,
copy: => This[N, E] @uV,
nodes: => Iterable[N],
edges: => Iterable[E[N]]): Either[ConstraintViolation, This[N, E]] =
if (checkSuspended) Right(copy)
else if (contained) Right(this)
else {
val preCheckResult = preAdd
preCheckResult.followUp match {
case Complete => Right(copy)
case PostCheck => postAdd(copy, nodes, edges, preCheckResult)
case Abort => Left(preCheckResult)
}
}

protected def checkedMinusNode(node: N,
forced: Boolean,
copy: (N, NodeT) => This[N, E] @uV): Either[ConstraintViolation, This[N, E]] =
nodes find node map { innerNode =>
def subtract = copy(node, innerNode)
if (checkSuspended)
Right(subtract)
else {
val preCheckResult = preSubtract(innerNode.asInstanceOf[self.NodeT], forced)
preCheckResult.followUp match {
case Complete => Right(subtract)
case PostCheck => postSubtract(subtract, Set(node), Set.empty[E[N]], preCheckResult)
case Abort => Left(preCheckResult)
}
}
} getOrElse Right(this)

protected def checkedMinusEdge(edge: E[N],
simple: Boolean,
copy: (E[N], EdgeT) => This[N, E] @uV): Either[ConstraintViolation, This[N, E]] =
edges find edge map { innerEdge =>
def subtract = copy(edge, innerEdge)
if (checkSuspended) Right(subtract)
else {
val preCheckResult = preSubtract(innerEdge.asInstanceOf[self.EdgeT], simple)
preCheckResult.followUp match {
case Complete => Right(subtract)
case PostCheck => postSubtract(subtract, Set.empty[N], Set(edge), preCheckResult)
case Abort => Left(preCheckResult)
}
}
} getOrElse Right(this)
}
@@ -0,0 +1,45 @@
package scalax.collection.constrained

import scala.collection.{GenTraversableOnce, Set}

import scalax.collection.GraphPredef.{EdgeLikeIn, Param}
import scalax.collection.{GraphLike => SimpleGraphLike}

/* Operations for constrained graphs that also return information on any constraint violation.
These ops are counterparts of non-constrained graph ops that do not expose constraint violations.
These enhanced ops bear the same name but a postfix `?` for operator identifiers respectively `_?` for plain identifiers.
$define Info returns additional information on any potential constraint violation
*/
trait GraphOps[
N,
E[+X] <: EdgeLikeIn[X],
+This[X, Y[+X] <: EdgeLikeIn[X]] <: GraphLike[X, Y, This] with Set[Param[X, Y]] with Graph[X, Y]
] { _: This[N, E] with SimpleGraphLike[N, E, This] with GraphOps[N, E, This] =>

/** Same as `+` but $Info. */
def +?(node: N): Either[ConstraintViolation, This[N, E]]

final override def +(elem: Param[N, E]): This[N, E] = +?(elem) getOrElse this

/** Same as `+` but $Info. */
def +?(elem: Param[N, E]): Either[ConstraintViolation, This[N, E]]

final override def ++(elems: GenTraversableOnce[Param[N, E]]): This[N, E] = ++?(elems) getOrElse this

/** Same as `++` but $Info. */
def ++?(elems: GenTraversableOnce[Param[N, E]]): Either[ConstraintViolation, This[N, E]]

/** Same as `-` but $Info. */
def -?(node: N): Either[ConstraintViolation, This[N, E]]

final override def -(elem: Param[N, E]): This[N, E] = -?(elem) getOrElse this

/** Same as `-` but $Info. */
def -?(elem: Param[N, E]): Either[ConstraintViolation, This[N, E]]

final override def --(elems: GenTraversableOnce[Param[N, E]]): This[N, E] = --?(elems) getOrElse this

/** Same as `--` but $Info. */
def --?(elems: GenTraversableOnce[Param[N, E]]): Either[ConstraintViolation, This[N, E]]
}

0 comments on commit f63e8f6

Please sign in to comment.