@@ -32,6 +32,9 @@ import org.gradle.api.plugins.quality.CheckstylePlugin
3232import org.gradle.api.plugins.quality.CodeNarc
3333import org.gradle.api.plugins.quality.CodeNarcExtension
3434import org.gradle.api.plugins.quality.CodeNarcPlugin
35+ import org.gradle.api.tasks.Copy
36+ import org.gradle.process.ExecSpec
37+ import org.apache.tools.ant.taskdefs.condition.Os
3538
3639@CompileStatic
3740class GrailsCodeStylePlugin implements Plugin<Project > {
@@ -49,6 +52,7 @@ class GrailsCodeStylePlugin implements Plugin<Project> {
4952 void apply (Project project ) {
5053 initExtension(project)
5154 configureCodeStyle(project)
55+ registerFormattingTasks(project)
5256 doNotApplyStylingToTests(project)
5357 }
5458
@@ -108,8 +112,10 @@ class GrailsCodeStylePlugin implements Plugin<Project> {
108112 }
109113
110114 private static void doNotApplyStylingToTests (Project project ) {
111- project. tasks. named(' checkstyleTest' ) {
112- it. enabled = false // Do not check test sources at this time
115+ if (project. tasks. names. contains(' checkstyleTest' )) {
116+ project. tasks. named(' checkstyleTest' ) {
117+ it. enabled = false // Do not check test sources at this time
118+ }
113119 }
114120
115121 project. afterEvaluate {
@@ -191,4 +197,88 @@ class GrailsCodeStylePlugin implements Plugin<Project> {
191197 )
192198 }
193199 }
200+
201+ private static void registerFormattingTasks (Project project ) {
202+ if (project == project. rootProject) {
203+ project. tasks. register(' installGitHooks' , Copy ) {
204+ it. group = ' verification'
205+ it. description = ' Installs the git pre-commit hook for automatic code formatting'
206+ it. from(project. rootProject. layout. projectDirectory. file(' etc/hooks/pre-commit' ))
207+ it. into(project. rootProject. layout. projectDirectory. dir(' .git/hooks' ))
208+ it. fileMode = 0755
209+ }
210+ }
211+
212+ project. tasks. register(' formatCode' ) {
213+ it. group = ' verification'
214+ it. description = ' Formats Java and Groovy source files using the IntelliJ command line formatter'
215+
216+ it. doLast {
217+ String ideaHome = (project. findProperty(' idea.home' ) ?: System . getenv(' IDEA_HOME' )) as String
218+ String executable = Os . isFamily(Os . FAMILY_WINDOWS ) ? ' format.bat' : ' format.sh'
219+ File formatExec = null
220+
221+ if (ideaHome) {
222+ formatExec = new File (ideaHome, " bin/$executable " )
223+ } else {
224+ // Try common paths on macOS
225+ if (Os . isFamily(Os . FAMILY_MAC )) {
226+ def commonPaths = [
227+ " /Applications/IntelliJ IDEA.app/Contents/bin/$executable " ,
228+ " /Applications/IntelliJ IDEA CE.app/Contents/bin/$executable "
229+ ]
230+ for (path in commonPaths) {
231+ File f = new File (path)
232+ if (f. exists()) {
233+ formatExec = f
234+ break
235+ }
236+ }
237+ }
238+
239+ if (formatExec == null && ! Os . isFamily(Os . FAMILY_WINDOWS )) {
240+ // On Linux/Mac, try to find 'idea' in PATH
241+ try {
242+ def out = new ByteArrayOutputStream ()
243+ project. exec { ExecSpec exec ->
244+ exec. commandLine ' which' , ' idea'
245+ exec. standardOutput = out
246+ exec. ignoreExitValue = true
247+ }
248+ def path = out. toString(). trim()
249+ if (path) {
250+ formatExec = new File (new File (path). parentFile, executable)
251+ }
252+ } catch (Exception ignored) { }
253+ }
254+ }
255+
256+ if (formatExec == null || ! formatExec. exists()) {
257+ project. logger. error(" IntelliJ formatter executable not found." )
258+ project. logger. error(" Please set 'idea.home' property or IDEA_HOME environment variable to your IntelliJ installation directory." )
259+ project. logger. error(" Example: ./gradlew formatCode -Pidea.home=/Applications/IntelliJ\\ IDEA.app/Contents" )
260+ throw new RuntimeException (" IntelliJ formatter executable not found." )
261+ }
262+
263+ def filesToFormat = project. findProperty(' formatFiles' )
264+ def settingsFile = project. rootProject. file(' .idea/codeStyles/Project.xml' )
265+
266+ if (! settingsFile. exists()) {
267+ throw new RuntimeException (" IntelliJ code style settings not found at ${ settingsFile.absolutePath} " )
268+ }
269+
270+ project. exec { ExecSpec exec ->
271+ exec. commandLine formatExec. absolutePath
272+ exec. args ' -s' , settingsFile. absolutePath
273+ exec. args ' -mask' , ' *.java,*.groovy'
274+ exec. args ' -r'
275+ if (filesToFormat) {
276+ exec. args((filesToFormat. toString()). split(' ,' ))
277+ } else {
278+ exec. args project. projectDir. absolutePath
279+ }
280+ }
281+ }
282+ }
283+ }
194284}
0 commit comments