Skip to content

Commit

Permalink
Refactor module and project descriptors into dedicated classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikko Peltonen authored and Mikko Peltonen committed Feb 5, 2010
1 parent 51429b5 commit 842d227
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 112 deletions.
54 changes: 54 additions & 0 deletions src/main/scala/IdeaModuleDescriptor.scala
@@ -0,0 +1,54 @@
import sbt.{Logger, BasicDependencyProject}
import xml.{XML, Node}

case class IdeaModuleDescriptor(val project: BasicDependencyProject, log: Logger) extends ProjectPaths {
def save: Unit = {
val moduleDescriptorPath = String.format("%s/%s.iml", projectPath, project.name)
XML.save(moduleDescriptorPath, moduleXml)
log.info("Created " + moduleDescriptorPath)
}

def moduleXml: Node = {
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Scala" name="Scala">
<configuration>
<option name="takeFromSettings" value="true" />
<option name="myScalaCompilerJarPath" value={String.format("$MODULE_DIR$/%s", relativePath(scalaCompilerJar))} />
<option name="myScalaSdkJarPath" value={String.format("$MODULE_DIR$/%s", relativePath(scalaLibraryJar))} />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/scala" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/scala" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="scala" level="project" />
{
project.info.dependencies.map { dep =>
log.info("Project dependency: " + dep.name)
<orderEntry type="module" module-name={dep.name} />
}
}
{
ideClasspath.getFiles.filter(_.getPath.endsWith(".jar")).map { jarFile =>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url={String.format("jar://$MODULE_DIR$/%s!/", relativePath(jarFile))} />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
}
}
</component>
</module>
}
}
114 changes: 2 additions & 112 deletions src/main/scala/IdeaPlugin.scala
@@ -1,120 +1,10 @@
import sbt._
import sbt.Configurations._
import java.io.File
import xml.{XML, Node}

trait IdeaPlugin extends BasicDependencyProject {
lazy val idea = task { createIdeaProject; None } dependsOn(update) describedAs("Creates IntelliJ IDEA project files.")

def createIdeaProject: Unit = {
if (info.parent.isEmpty) {
val projectDescriptorPath = String.format("%s/%s.ipr", projectPath, name)
XML.save(projectDescriptorPath, projectXml)
log.info("Created " + projectDescriptorPath)
}
val moduleDescriptorPath = String.format("%s/%s.iml", projectPath, name)
XML.save(moduleDescriptorPath, moduleXml)
log.info("Created " + moduleDescriptorPath)
}

def projectPath: File = info.projectPath.asFile
def childProjects: List[(String, String)] = subProjects.values.toList.map { s =>
(projectRelativePath(s.info.projectPath.asFile), s.name)
}

def projectRelativePath(target: File): String = {
def pathComponentsOf(f: File): List[String] = {
val p = f.getParentFile
if (p == null) Nil else List(f.getName) ::: pathComponentsOf(p)
}
val projectPathComponents = pathComponentsOf(projectPath).reverseMap(Some(_))
val targetPathComponents = pathComponentsOf(target).reverseMap(Some(_))
val pathComponents = projectPathComponents.zipAll(targetPathComponents, None, None).dropWhile(x => x._1 == x._2)
val (projectBranch, targetBranch) = List.unzip(pathComponents)
val prefix = projectBranch.takeWhile(_ != None).foldLeft("")((acc, x) => acc + "../")
val suffix = targetBranch.takeWhile(_ != None).foldLeft("")((acc, x) => acc + (if (acc != "") "/" else "") + x.get)
prefix + suffix
}

def ideClasspath: PathFinder = fullClasspath(Runtime) +++ managedClasspath(Optional) +++ fullClasspath(Test)
def buildScalaJarDir: Path = rootProject.info.bootPath / String.format("scala-%s", buildScalaVersion) / "lib"
def scalaCompilerJar: File = (buildScalaJarDir / "scala-compiler.jar").asFile
def scalaLibraryJar: File = (buildScalaJarDir / "scala-library.jar").asFile

def projectXml: Node = {
<project version="4">
<component name="ProjectDetails">
<option name="projectName" value={name} />
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl={String.format("file://$PROJECT_DIR$/%s.iml", name)} filepath={String.format("$PROJECT_DIR$/%s.iml", name)} />
{
childProjects.map { case (modulePath, moduleName) =>
<module fileurl={String.format("file://$PROJECT_DIR$/%s/%s.iml", modulePath, moduleName)} filepath={String.format("$PROJECT_DIR$/%s/%s.iml", modulePath, moduleName)} />
}
}
</modules>
</component>
{
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
}
<component name="libraryTable">
<library name="scala">
<CLASSES>
<root url={String.format("jar://$PROJECT_DIR$/%s!/", projectRelativePath(scalaCompilerJar))} />
<root url={String.format("jar://$PROJECT_DIR$/%s!/", projectRelativePath(scalaLibraryJar))} />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
</project>
}

def moduleXml: Node = {
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Scala" name="Scala">
<configuration>
<option name="takeFromSettings" value="true" />
<option name="myScalaCompilerJarPath" value={String.format("$MODULE_DIR$/%s", projectRelativePath(scalaCompilerJar))} />
<option name="myScalaSdkJarPath" value={String.format("$MODULE_DIR$/%s", projectRelativePath(scalaLibraryJar))} />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/scala" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/scala" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="scala" level="project" />
{
info.dependencies.map { dep =>
log.info("Project dependency: " + dep.name)
<orderEntry type="module" module-name={dep.name} />
}
}
{
ideClasspath.getFiles.filter(_.getPath.endsWith(".jar")).map { jarFile =>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url={String.format("jar://$MODULE_DIR$/%s!/", projectRelativePath(jarFile))} />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
}
}
</component>
</module>
if (info.parent.isEmpty) IdeaProjectDescriptor(this, log).save
IdeaModuleDescriptor(this, log).save
}
}
43 changes: 43 additions & 0 deletions src/main/scala/IdeaProjectDescriptor.scala
@@ -0,0 +1,43 @@
import sbt.{Logger, BasicDependencyProject}
import xml.{XML, Node}

case class IdeaProjectDescriptor(val project: BasicDependencyProject, log: Logger) extends ProjectPaths {
def save: Unit = {
val projectDescriptorPath = String.format("%s/%s.ipr", projectPath, project.name)
XML.save(projectDescriptorPath, projectXml)
log.info("Created " + projectDescriptorPath)
}

def projectXml: Node = {
<project version="4">
<component name="ProjectDetails">
<option name="projectName" value={project.name} />
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl={String.format("file://$PROJECT_DIR$/%s.iml", project.name)} filepath={String.format("$PROJECT_DIR$/%s.iml", project.name)} />
{
childProjects.map { case (modulePath, moduleName) =>
<module fileurl={String.format("file://$PROJECT_DIR$/%s/%s.iml", modulePath, moduleName)} filepath={String.format("$PROJECT_DIR$/%s/%s.iml", modulePath, moduleName)} />
}
}
</modules>
</component>
{
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
}
<component name="libraryTable">
<library name="scala">
<CLASSES>
<root url={String.format("jar://$PROJECT_DIR$/%s!/", relativePath(scalaCompilerJar))} />
<root url={String.format("jar://$PROJECT_DIR$/%s!/", relativePath(scalaLibraryJar))} />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
</project>
}
}
30 changes: 30 additions & 0 deletions src/main/scala/ProjectPaths.scala
@@ -0,0 +1,30 @@
import java.io.File
import sbt.Configurations._
import sbt.{Path, PathFinder, BasicDependencyProject}

trait ProjectPaths {
val project: BasicDependencyProject

def projectPath: File = project.info.projectPath.asFile
def childProjects: List[(String, String)] = project.subProjects.values.toList.map { s =>
(relativePath(s.info.projectPath.asFile), s.name)
}
def relativePath(targetPath: File): String = {
def pathComponentsOf(f: File): List[String] = {
val p = f.getParentFile
if (p == null) Nil else List(f.getName) ::: pathComponentsOf(p)
}
val basePathComponents = pathComponentsOf(projectPath).reverseMap(Some(_))
val targetPathComponents = pathComponentsOf(targetPath).reverseMap(Some(_))
val pathComponents = basePathComponents.zipAll(targetPathComponents, None, None).dropWhile(x => x._1 == x._2)
val (baseBranch, targetBranch) = List.unzip(pathComponents)
val prefix = baseBranch.takeWhile(_ != None).foldLeft("")((acc, x) => acc + ".." + File.separator)
val suffix = targetBranch.takeWhile(_ != None).foldLeft("")((acc, x) => acc + (if (acc != "") File.separator else "") + x.get)
prefix + suffix
}

def ideClasspath: PathFinder = project.fullClasspath(Runtime) +++ project.managedClasspath(Optional) +++ project.fullClasspath(Test)
def buildScalaJarDir: Path = project.rootProject.info.bootPath / String.format("scala-%s", project.buildScalaVersion) / "lib"
def scalaCompilerJar: File = (buildScalaJarDir / "scala-compiler.jar").asFile
def scalaLibraryJar: File = (buildScalaJarDir / "scala-library.jar").asFile
}

0 comments on commit 842d227

Please sign in to comment.