Skip to content

Instantly share code, notes, and snippets.

@dmarcato
Forked from chrisfesler/build_intellij_sync.gradle
Last active December 18, 2015 06:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmarcato/5743419 to your computer and use it in GitHub Desktop.
Save dmarcato/5743419 to your computer and use it in GitHub Desktop.
/**
* apply this plugin after doing all dependency and repo stuff. It will create two idea 'libraries' per subproject
* and add them to your .iml files
*
* Forked from https://gist.github.com/360092
*
* Plugin-ified and made to support multiple modules per root build.gradle and multiple build.gradles per idea project.
*/
class IntelliJSync implements Plugin<Project> {
def sep = File.separator
@Override
void apply(Project project) {
configureIntellijSync(project)
configureIntellijLibrarySync(project)
configureIntellijModuleSync(project)
}
def configureIntellijSync(Project project) {
project.tasks.add('intellijSync', DefaultTask.class).with {
description = "Sync libraries and modules with gradle dependencies"
dependsOn 'intellijLibrarySync'
dependsOn 'intellijModuleSync'
}
}
def configureIntellijLibrarySync(Project project) {
project.tasks.add('intellijLibrarySync', DefaultTask.class).with {
description = "Add gradle dependecies to IntelliJ project libraries in ${findIdeaLibrariesDir()}"
doLast {
final File librariesDir = findIdeaLibrariesDir()
librariesDir.mkdirs()
final def userHomeGradle = project.gradle.gradleUserHomeDir
logger.info("In IDEA's settings->path variables, ensure that USER_HOME_GRADLE is set to '$userHomeGradle.path'")
def makeJarList = { path ->
path.split(File.pathSeparator).collect {
it.replaceAll userHomeGradle.path, "\\\$USER_HOME_GRADLE\\\$"
}
}
final def compileJars = makeJarList(project.configurations.compile.asPath)
final def testJars = makeJarList(project.configurations.testCompile.asPath) - compileJars
def createLibrary = { fileName, libraryName, jars ->
final def gradleLibXml = new File(librariesDir, fileName)
gradleLibXml.write """
<component name="libraryTable">
<library name="$libraryName"/>
</component>"""
final def xmlRoot = new XmlParser().parse(gradleLibXml)
final def classesNode = xmlRoot.library[0].appendNode('CLASSES')
jars.each { jar ->
classesNode.appendNode('root', [url: "jar://$jar!/"])
}
def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(xmlRoot)
gradleLibXml.write writer.toString()
logger.info("File '${gradleLibXml.canonicalPath}' updated")
}
createLibrary libFile(project), libName(project), compileJars
createLibrary testFile(project), testName(project), testJars
}
}
}
def configureIntellijModuleSync(Project project) {
project.tasks.add('intellijModuleSync', DefaultTask.class).with {
description = "Add to generated project libraries to IntelliJ .iml files"
doLast {
final def moduleFile = new File("${project.name}.iml")
if (moduleFile.exists()) {
def root = new XmlParser().parse(moduleFile)
def newModuleRootManager = root.component.find {it.'@name' == 'NewModuleRootManager'}
// find and remove old entries for test and lib
[libName(project), testName(project)].each { orderEntryName ->
def orderEntry = newModuleRootManager.orderEntry.find {
it.'@type' == 'library' && it.'@name' == orderEntryName
}
if (orderEntry) {
newModuleRootManager.remove(orderEntry)
}
}
// make the new entries
newModuleRootManager.appendNode('orderEntry', [type: 'library', scope: 'TEST', name: testName(project), level: 'project'])
newModuleRootManager.appendNode('orderEntry', [type: 'library', exported: '', name: libName(project), level: 'project'])
def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(root)
moduleFile.write writer.toString()
logger.info("File '${moduleFile.canonicalPath}' updated")
}
else {
logger.info("skipping module ${moduleFile}")
}
}
}
}
// ////////////////////////
// MINIONS
// ////////////////////////
def libName(Project project) {
"${project.name} Gradle Libs"
}
def libFile(Project project) {
toFile(libName(project))
}
def testName(Project project) {
"${project.name} Gradle Test Libs"
}
def testFile(Project project) {
toFile(testName(project))
}
def toFile(String libName) {
libName.replace(' ', "_") + ".xml"
}
def findIdeaLibrariesDir() {
// walk up the current path, looking for .idea/workspace.xml, rather than simply using .idea in the current
// directory. This is to support cases where one idea project contains multiple root-level build.gradle files
def start = new File(".")
def dotIdea = findDotIdea(start)
if (!dotIdea) {
// we tried -- no pre-existing .idea project file above us. We'll just suppose that it hasn't been created yet, and
// belongs in the current directory.
dotIdea = start
}
new File("${dotIdea}${sep}libraries")
}
def findDotIdea(File ideaProjectRoot) {
// use canonicalPath to ensure .parent works reliably.
ideaProjectRoot = new File(ideaProjectRoot.canonicalPath)
// for back-compatibility, look for a .idea/workspace.xml, not just .idea
File dotIdea = new File("${ideaProjectRoot.path}${sep}.idea")
File workspace = new File("${dotIdea.path}${sep}workspace.xml")
if (workspace.exists()) {
dotIdea
}
else if (ideaProjectRoot.parent) {
findDotIdea(new File(ideaProjectRoot.parent))
}
else {
null
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment