Skip to content

Commit

Permalink
closes #51: Add support for configurations
Browse files Browse the repository at this point in the history
  • Loading branch information
Heiko Seeberger committed Dec 20, 2011
1 parent d03c111 commit 5943506
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 61 deletions.
92 changes: 50 additions & 42 deletions src/main/scala/com/typesafe/sbteclipse/Eclipse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@

package com.typesafe.sbteclipse

import EclipsePlugin.{ ClasspathEntry, EclipseExecutionEnvironment }
import EclipsePlugin.{ ClasspathEntry, EclipseExecutionEnvironment, EclipseKeys }
import java.io.FileWriter
import java.util.Properties
import sbt.{ Command, Configurations, File, IO, Keys, Project, ProjectRef, ResolvedProject, State, ThisBuild, richFile }
import sbt.{ Command, Configuration, Configurations, File, IO, Keys, Project, ProjectRef, ResolvedProject, State, ThisBuild, richFile }
import sbt.CommandSupport.logger
import scala.collection.JavaConverters
import scala.xml.{ Elem, NodeSeq, PrettyPrinter }
Expand All @@ -38,8 +38,8 @@ private object Eclipse {
executionEnvironment: Option[EclipseExecutionEnvironment.Value],
skipParents: Boolean,
withSource: Boolean,
commandName: String,
classpathEntryCollector: PartialFunction[ClasspathEntry, ClasspathEntry]): Command =
classpathEntryCollector: PartialFunction[ClasspathEntry, ClasspathEntry],
commandName: String): Command =
Command(commandName)(_ => parser)((state, args) =>
action(executionEnvironment, skipParents, withSource, classpathEntryCollector, args.toMap)(state)
)
Expand Down Expand Up @@ -74,14 +74,15 @@ private object Eclipse {
ref <- structure.allProjectRefs
project <- Project.getProject(ref, structure) if project.aggregate.isEmpty || !skipParents
} yield {
val cs = configurations(ref)
(name(ref) |@|
buildDirectory(ref) |@|
baseDirectory(ref) |@|
compileSrcDirectories(ref) |@|
testSrcDirectories(ref) |@|
((cs map srcDirectories(ref)).sequence[ValidationNELS, Seq[(File, File)]] map (_.flatten.distinct)) |@|
target(ref) |@|
scalacOptions(ref) |@|
externalDependencies(ref) |@|
projectDependencies(ref, project))(content(classpathEntryCollector))
((cs map externalDependencies(ref)).sequence[ValidationNELS, Seq[File]] map (_.flatten.distinct)) |@|
((cs map projectDependencies(ref, project)).sequence[ValidationNELS, Seq[String]] map (_.flatten.distinct)))(content(classpathEntryCollector))
}
contents.sequence[ValidationNELS, Content]
}
Expand All @@ -106,8 +107,8 @@ private object Eclipse {
name: String,
buildDirectory: File,
baseDirectory: File,
compileSrcDirectories: (Seq[File], File),
testSrcDirectories: (Seq[File], File),
srcDirectories: Seq[(File, File)],
target: File,
scalacOptions: Seq[(String, String)],
externalDependencies: Seq[File],
projectDependencies: Seq[String])(
Expand All @@ -120,8 +121,8 @@ private object Eclipse {
classpathEntryCollector,
buildDirectory,
baseDirectory,
compileSrcDirectories,
testSrcDirectories,
srcDirectories,
target,
externalDependencies,
projectDependencies
),
Expand All @@ -145,31 +146,30 @@ private object Eclipse {
classpathEntryCollector: PartialFunction[ClasspathEntry, ClasspathEntry],
buildDirectory: File,
baseDirectory: File,
compileSrcDirectories: (Seq[File], File),
testSrcDirectories: (Seq[File], File),
srcDirectories: Seq[(File, File)],
target: File,
externalDependencies: Seq[File],
projectDependencies: Seq[String])(
implicit state: State) = {
val entries =
Seq(
compileSrcDirectories._1 flatMap srcEntry(baseDirectory, compileSrcDirectories._2),
testSrcDirectories._1 flatMap srcEntry(baseDirectory, testSrcDirectories._2),
externalDependencies map libEntry(buildDirectory, baseDirectory),
projectDependencies map ClasspathEntry.Project,
Seq("org.eclipse.jdt.launching.JRE_CONTAINER") map ClasspathEntry.Con, // TODO Optionally use execution env!
Seq(output(baseDirectory, compileSrcDirectories._2)) map ClasspathEntry.Output
).flatten collect classpathEntryCollector map (_.toXml)
val entries = Seq(
(for ((dir, output) <- srcDirectories) yield srcEntry(baseDirectory, output)(dir)).flatten.distinct,
externalDependencies map libEntry(buildDirectory, baseDirectory),
projectDependencies map ClasspathEntry.Project,
Seq("org.eclipse.jdt.launching.JRE_CONTAINER") map ClasspathEntry.Con, // TODO Optionally use execution env!
Seq(output(baseDirectory, target)) map ClasspathEntry.Output
).flatten collect classpathEntryCollector map (_.toXml)
<classpath>{ entries }</classpath>
}

def srcEntry(baseDirectory: File, classDirectory: File)(srcDirectory: File)(implicit state: State) =
def srcEntry(baseDirectory: File, classDirectory: File)(srcDirectory: File)(implicit state: State) = {
if (srcDirectory.exists()) {
logger(state).debug("Creating src entry for directory '%s'." format srcDirectory)
Some(ClasspathEntry.Src(relativize(baseDirectory, srcDirectory), output(baseDirectory, classDirectory)))
} else {
logger(state).debug("Skipping src entry for not-existing directory '%s'." format srcDirectory)
None
}
}

def libEntry(buildDirectory: File, baseDirectory: File)(file: File)(implicit state: State) = {
val path =
Expand All @@ -182,26 +182,31 @@ private object Eclipse {
// Getting and transforming settings and task results

def name(ref: ProjectRef)(implicit state: State) =
setting(Keys.name, ref)
setting(Keys.name, ref, Configurations.Default)

def buildDirectory(ref: ProjectRef)(implicit state: State) =
setting(Keys.baseDirectory, ThisBuild)
setting(Keys.baseDirectory, ThisBuild, Configurations.Default)

def baseDirectory(ref: ProjectRef)(implicit state: State) =
setting(Keys.baseDirectory, ref)
setting(Keys.baseDirectory, ref, Configurations.Default)

def configurations(ref: ProjectRef)(implicit state: State) =
setting(EclipseKeys.configurations, ref, Configurations.Default).fold(
_ => Seq(Configurations.Compile, Configurations.Test),
_.toSeq
)

def compileSrcDirectories(ref: ProjectRef)(implicit state: State) =
(setting(Keys.sourceDirectories, ref) |@|
setting(Keys.resourceDirectories, ref) |@|
setting(Keys.classDirectory, ref))(srcDirsToOutput)
def target(ref: ProjectRef)(implicit state: State) =
setting(Keys.target, ref, Configurations.Default)

def testSrcDirectories(ref: ProjectRef)(implicit state: State) =
(setting(Keys.sourceDirectories, ref, Configurations.Test) |@|
setting(Keys.resourceDirectories, ref, Configurations.Test) |@|
setting(Keys.classDirectory, ref, Configurations.Test))(srcDirsToOutput)
def srcDirectories(ref: ProjectRef)(configuration: Configuration)(implicit state: State) = {
(setting(Keys.sourceDirectories, ref, configuration) |@|
setting(Keys.resourceDirectories, ref, configuration) |@|
setting(Keys.classDirectory, ref, configuration))(srcDirsToOutput)
}

def scalacOptions(ref: ProjectRef)(implicit state: State) =
evaluateTask(Keys.scalacOptions, ref) map { options =>
evaluateTask(Keys.scalacOptions, ref, Configurations.Default) map { options =>
def values(value: String) =
value split "," map (_.trim) filterNot (_ contains "org.scala-lang.plugins/continuations")
options collect {
Expand All @@ -215,12 +220,15 @@ private object Eclipse {
}
}

def externalDependencies(ref: ProjectRef)(implicit state: State) =
evaluateTask(Keys.externalDependencyClasspath, ref, Configurations.Test) map (_.files)
def externalDependencies(ref: ProjectRef)(configuration: Configuration)(implicit state: State) =
evaluateTask(Keys.externalDependencyClasspath, ref, configuration) map (_.files)

def projectDependencies(ref: ProjectRef, project: ResolvedProject)(implicit state: State) = {
val projectDependencies = project.dependencies map (dependency => setting(Keys.name, dependency.project))
projectDependencies.distinct.sequence
def projectDependencies(ref: ProjectRef, project: ResolvedProject)(configuration: Configuration)(implicit state: State) = {
val projectDependencies = project.dependencies collect {
case dependency if dependency.configuration map (_ == configuration) getOrElse true =>
setting(Keys.name, dependency.project)
}
projectDependencies.sequence
}

// Writing to disk
Expand Down Expand Up @@ -251,7 +259,7 @@ private object Eclipse {
// Utilities

def srcDirsToOutput(sourceDirectories: Seq[File], resourceDirectories: Seq[File], output: File) =
(sourceDirectories ++ resourceDirectories).distinct -> output
(sourceDirectories ++ resourceDirectories) map (_ -> output)

def relativize(baseDirectory: File, file: File) = IO.relativize(baseDirectory, file).get

Expand Down
21 changes: 13 additions & 8 deletions src/main/scala/com/typesafe/sbteclipse/EclipsePlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package com.typesafe.sbteclipse

import sbt.{ File, Plugin, Setting, SettingKey }
import sbt.{ Configuration, Configurations, File, Plugin, Setting, SettingKey }
import sbt.Keys.{ baseDirectory, commands }
import scala.xml.Elem

Expand All @@ -30,14 +30,14 @@ object EclipsePlugin extends Plugin {
executionEnvironment := None,
skipParents := true,
withSource := false,
commandName := "eclipse",
classpathEntryCollector := eclipseDefaultClasspathEntryCollector,
commandName := "eclipse",
commands <+= (
executionEnvironment,
skipParents,
withSource,
commandName,
classpathEntryCollector
classpathEntryCollector,
commandName
)(Eclipse.eclipseCommand)
)
}
Expand Down Expand Up @@ -69,15 +69,20 @@ object EclipsePlugin extends Plugin {
prefix(WithSource),
"Download and link sources for library dependencies?")

val classpathEntryCollector: SettingKey[PartialFunction[ClasspathEntry, ClasspathEntry]] =
SettingKey[PartialFunction[ClasspathEntry, ClasspathEntry]](
prefix("classpathEntryCollector"),
"Determines how classpath entries are filtered and transformed before written into XML.")

val commandName: SettingKey[String] =
SettingKey[String](
prefix("command-name"),
"The name of the command.")

val classpathEntryCollector: SettingKey[PartialFunction[ClasspathEntry, ClasspathEntry]] =
SettingKey[PartialFunction[ClasspathEntry, ClasspathEntry]](
prefix("classpathEntryCollector"),
"Determines how classpath entries are filtered and transformed before written into XML.")
val configurations: SettingKey[Set[Configuration]] =
SettingKey[Set[Configuration]](
prefix("configurations"),
"The configurations to take into account.")

private def prefix(key: String) = "eclipse-" + key
}
Expand Down
37 changes: 32 additions & 5 deletions src/sbt-test/sbteclipse/02-contents/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ TaskKey[Unit]("verify-project-xml") <<= baseDirectory map { dir =>
}

TaskKey[Unit]("verify-classpath-xml-root") <<= baseDirectory map { dir =>
// src entries
val classpath = XML.loadFile(dir / ".classpath")
if ((classpath \ "classpathentry") != (classpath \ "classpathentry").distinct)
error("Expected .classpath of root project not to contain duplicate entries: %s" format classpath)
// src entries
if (!(classpath.child contains <classpathentry kind="src" path="src/main/scala" output="target/scala-2.9.1/classes" />))
error("""Expected .classpath of root project to contain <classpathentry kind="src" path="src/main/scala" output="target/scala-2.9.1/classes" /> """)
if (!(classpath.child contains <classpathentry kind="src" path="src/main/java" output="target/scala-2.9.1/classes" />))
Expand All @@ -35,6 +35,8 @@ TaskKey[Unit]("verify-classpath-xml-root") <<= baseDirectory map { dir =>
error("""Not expected .classpath of root project to contain <classpathentry kind="..." path="src/test/java" output="..." /> """)
if ((classpath \ "classpathentry" \\ "@path") map (_.text) contains "src/test/resources")
error("""Not expected .classpath of root project to contain <classpathentry kind="..." path="src/test/resources" output="..." /> """)
if ((classpath \ "classpathentry" \\ "@path") map (_.text) contains "src/it/scala")
error("""Not expected .classpath of root project to contain <classpathentry kind="..." path="src/it/scala" output="..." /> """)
// other entries
if ((classpath \ "classpathentry" \\ "@path") map (_.text) contains "scala-library.jar")
error("""Not expected .classpath of root project to contain <classpathentry path="...scala-library.jar" ... /> """)
Expand All @@ -46,22 +48,47 @@ TaskKey[Unit]("verify-classpath-xml-root") <<= baseDirectory map { dir =>
error("""Expected .classpath of root project to contain <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_COMPILER_CONTAINER"/> """)
if (!(classpath.child contains <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>))
error("""Expected .classpath of root project to contain <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> """)
if (!(classpath.child contains <classpathentry kind="output" path="target/scala-2.9.1/classes"/>))
error("""Expected .classpath of root project to contain <classpathentry kind="output" path="target/scala-2.9.1/classes"/> """)
if (!(classpath.child contains <classpathentry kind="output" path="target"/>))
error("""Expected .classpath of root project to contain <classpathentry kind="output" path="target"/> """)
}

TaskKey[Unit]("verify-classpath-xml-subb") <<= baseDirectory map { dir =>
// src entries
TaskKey[Unit]("verify-classpath-xml-suba") <<= baseDirectory map { dir =>
val home = System.getProperty("user.home")
val classpath = XML.loadFile(dir / "sub" / "suba" / ".classpath")
if ((classpath \ "classpathentry") != (classpath \ "classpathentry").distinct)
error("Expected .classpath of suba project not to contain duplicate entries: %s" format classpath)
// lib entries without sources
if (!(classpath.child contains <classpathentry kind="lib" path={ home + "/.ivy2/cache/com.weiglewilczek.slf4s/slf4s_2.9.1/jars/slf4s_2.9.1-1.0.7.jar" } />))
error("""Expected .classpath of suba project to contain <classpathentry kind="lib" path={ home + "/.ivy2/cache/com.weiglewilczek.slf4s/slf4s_2.9.1/jars/slf4s_2.9.1-1.0.7.jar" } />: %s""" format classpath)
if (!(classpath.child contains <classpathentry kind="lib" path={ home + "/.ivy2/cache/biz.aQute/bndlib/jars/bndlib-1.50.0.jar" } />))
error("""Expected .classpath of suba project to contain <classpathentry kind="lib" path={ home + "/.ivy2/cache/biz.aQute/bndlib/jars/bndlib-1.50.0.jar" } />: %s""" format classpath)
if (!(classpath.child contains <classpathentry kind="lib" path={ home + "/.ivy2/cache/org.specs2/specs2_2.9.1/jars/specs2_2.9.1-1.6.1.jar" } />))
error("""Expected .classpath of suba project to contain <classpathentry kind="lib" path={ home + "/.ivy2/cache/org.specs2/specs2_2.9.1/jars/specs2_2.9.1-1.6.1.jar" } />: %s""" format classpath)
}

TaskKey[Unit]("verify-classpath-xml-subb") <<= baseDirectory map { dir =>
val classpath = XML.loadFile(dir / "sub" / "subb" / ".classpath")
if ((classpath \ "classpathentry") != (classpath \ "classpathentry").distinct)
error("Expected .classpath of subb project not to contain duplicate entries: %s" format classpath)
// src entries
if (!(classpath.child contains <classpathentry kind="src" path="src/it/scala" output="target/scala-2.9.1/it-classes" />))
error("""Expected .classpath of subb project to contain <classpathentry kind="src" path="src/it/scala" output="target/scala-2.9.1/it-classes" />: %s""" format classpath)
if ((classpath \ "classpathentry" \\ "@path") map (_.text) contains "src/test/scala")
error("""Not expected .classpath of root project to contain <classpathentry kind="..." path="src/test/scala" output="..." /> """)
// lib entries without sources
if (!(classpath.child contains <classpathentry kind="lib" path="../../lib_managed/jars/com.weiglewilczek.slf4s/slf4s_2.9.1/slf4s_2.9.1-1.0.7.jar" />))
error("""Expected .classpath of subb project to contain <classpathentry kind="lib" path="../../lib_managed/jars/com.weiglewilczek.slf4s/slf4s_2.9.1/slf4s_2.9.1-1.0.7.jar" />: %s""" format classpath)
if (!(classpath.child contains <classpathentry kind="lib" path="../../lib_managed/jars/biz.aQute/bndlib/bndlib-1.50.0.jar" />))
error("""Expected .classpath of subb project to contain <classpathentry kind="lib" path="../../lib_managed/jars/biz.aQute/bndlib/bndlib-1.50.0.jar" />: %s""" format classpath)
if (!(classpath.child contains <classpathentry kind="lib" path="../../lib_managed/jars/junit/junit/junit-4.7.jar" />))
error("""Expected .classpath of subb project to contain <classpathentry kind="lib" path="../../lib_managed/jars/junit/junit/junit-4.7.jar" />: %s""" format classpath)
if ((classpath \ "classpathentry" \\ "@path") map (_.text) contains "specs2_2.9.1")
error("""Not expected .classpath of subb project to contain <classpathentry kind="..." path="...specs2_2.9.1..." output="..." /> """)
// project dependencies
if (!(classpath.child contains <classpathentry kind="src" path="/suba" exported="true" combineaccessrules="false" />))
error("""Expected .classpath of subb project to contain <classpathentry kind="src" path="/suba" exported="true" combineaccessrules="false" />: %s""" format classpath)
if ((classpath \ "classpathentry" \\ "@path") map (_.text) contains "/subc")
error("""Not expected .classpath of subb project to contain <classpathentry kind="..." path="...subc..." output="..." /> """)
}

TaskKey[Unit]("verify-settings") <<= baseDirectory map { dir =>
Expand Down
21 changes: 15 additions & 6 deletions src/sbt-test/sbteclipse/02-contents/project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object Build extends Build {
settings = Project.defaultSettings ++ Seq(
EclipseKeys.executionEnvironment := Some(EclipseExecutionEnvironment.JavaSE16)
),
aggregate = Seq(suba, subb)
aggregate = Seq(suba, subb, subc)
)

lazy val suba = Project(
Expand All @@ -32,21 +32,30 @@ object Build extends Build {
settings = Project.defaultSettings ++ Seq(
libraryDependencies ++= Seq(
"com.weiglewilczek.slf4s" %% "slf4s" % "1.0.7",
"biz.aQute" % "bndlib" % "1.50.0"
"biz.aQute" % "bndlib" % "1.50.0",
"org.specs2" %% "specs2" % "1.6.1" % "test"
)
)
)

lazy val subb = Project(
"subb",
new File("sub/subb"),
settings = Project.defaultSettings ++ Seq(
configurations = Configurations.default :+ Configurations.IntegrationTest,
settings = Project.defaultSettings ++ Defaults.itSettings ++ Seq(
libraryDependencies ++= Seq(
"biz.aQute" % "bndlib" % "1.50.0"
"biz.aQute" % "bndlib" % "1.50.0",
"junit" % "junit" % "4.7" % "it"
),
retrieveManaged := true,
scalacOptions := Seq("-unchecked", "-deprecation")
scalacOptions := Seq("-unchecked", "-deprecation"),
EclipseKeys.configurations := Set(Configurations.Compile, Configurations.IntegrationTest)
),
dependencies = Seq(suba, suba % "test->test")
dependencies = Seq(suba, suba % "test->compile", subc % "test->test")
)

lazy val subc = Project(
"subc",
new File("sub/subc")
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
object RootIt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object SubC {
def subC = "subC"
}
1 change: 1 addition & 0 deletions src/sbt-test/sbteclipse/02-contents/test
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ $ mkdir target/scala-2.9.1/src_managed/main
> eclipse skip-parents=false
> verify-project-xml
> verify-classpath-xml-root
> verify-classpath-xml-suba
> verify-classpath-xml-subb
> verify-settings

0 comments on commit 5943506

Please sign in to comment.