├── .gitignore ├── .travis.yml ├── LICENSE ├── README.adoc ├── build.gradle ├── config ├── HEADER ├── checkstyle │ └── checkstyle.xml └── codenarc │ └── codenarc.groovy ├── gradle.properties ├── gradle ├── code-coverage.gradle ├── code-quality.gradle ├── publishing.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── main ├── groovy │ └── org │ │ └── kordamp │ │ └── gradle │ │ └── stats │ │ ├── AggregateStatsReportTask.groovy │ │ ├── Counter.groovy │ │ ├── CssCounter.groovy │ │ ├── HashCounter.groovy │ │ ├── JavaCounter.groovy │ │ ├── PropertiesCounter.groovy │ │ ├── SemiColonCounter.groovy │ │ ├── SqlCounter.groovy │ │ ├── StatsPlugin.groovy │ │ ├── StatsTask.groovy │ │ └── XmlCounter.groovy └── resources │ └── META-INF │ └── gradle-plugins │ └── org.kordamp.gradle.stats.properties └── test ├── groovy └── org │ └── kordamp │ └── gradle │ └── stats │ ├── StatsPluginSpec.groovy │ └── StatsTaskSpec.groovy └── projects ├── basic_all └── src │ └── main │ └── java │ └── basic │ ├── Bar.groovy │ ├── Foo.java │ ├── foo.clj │ ├── foo.css │ ├── foo.fxml │ ├── foo.html │ ├── foo.js │ ├── foo.properties │ ├── foo.scss │ ├── foo.sql │ ├── foo.xml │ └── foo.yaml ├── basic_griffon ├── griffon-app │ ├── conf │ │ └── Config.groovy │ ├── controllers │ │ └── org │ │ │ └── example │ │ │ └── SampleController.groovy │ ├── i18n │ │ └── messages.properties │ ├── lifecycle │ │ └── Initialize.groovy │ ├── models │ │ └── org │ │ │ └── example │ │ │ └── SampleModel.groovy │ ├── resources │ │ ├── application.properties │ │ ├── griffon-icon-128x128.png │ │ ├── griffon-icon-16x16.png │ │ ├── griffon-icon-24x24.png │ │ ├── griffon-icon-256x256.png │ │ ├── griffon-icon-32x32.png │ │ ├── griffon-icon-48x48.png │ │ ├── griffon-icon-64x64.png │ │ ├── griffon.png │ │ └── resources.properties │ └── views │ │ └── org │ │ └── example │ │ └── SampleView.groovy └── src │ ├── integration-test │ └── groovy │ │ └── org │ │ └── example │ │ └── SampleIntegrationTest.groovy │ ├── main │ ├── groovy │ │ └── org │ │ │ └── example │ │ │ ├── ApplicationEventHandler.groovy │ │ │ ├── ApplicationModule.groovy │ │ │ ├── Foo.java │ │ │ └── Launcher.groovy │ ├── java │ │ └── org │ │ │ └── example │ │ │ └── Bar.java │ └── resources │ │ └── log4j.properties │ └── test │ └── groovy │ └── org │ └── example │ └── SampleControllerTest.groovy ├── basic_java └── src │ └── main │ └── java │ └── basic │ ├── Bar.java │ └── Foo.java └── basic_scala └── src └── main └── java └── basic ├── Bar.scala └── Foo.scala /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | build/ 3 | target/ 4 | out/ 5 | *.iml 6 | *.ipr 7 | *.iws 8 | .idea/ 9 | userHome/ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | script: ./gradlew clean build jacocoTestReport 3 | jdk: oraclejdk8 4 | before_cache: 5 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 6 | cache: 7 | directories: 8 | - $HOME/.gradle/caches/ 9 | - $HOME/.gradle/wrapper/ 10 | - $HOME/.sonar/cache/ 11 | addons: 12 | apt: 13 | packages: 14 | - oracle-java8-installer 15 | env: TERM=dumb 16 | after_success: ./gradlew coveralls 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | Stats Gradle Plugin 2 | =================== 3 | :linkattrs: 4 | :project-name: stats-gradle-plugin 5 | :plugin-version: 0.2.2 6 | 7 | image:http://img.shields.io/travis/aalmiray/{project-name}/master.svg["Build Status", link="https://travis-ci.org/aalmiray/{project-name}"] 8 | image:http://img.shields.io/coveralls/aalmiray/{project-name}/master.svg["Coverage Status", link="https://coveralls.io/r/aalmiray/{project-name}"] 9 | image:http://img.shields.io/badge/license-ASF2-blue.svg["Apache License 2", link="http://www.apache.org/licenses/LICENSE-2.0.txt"] 10 | image:https://api.bintray.com/packages/aalmiray/kordamp/{project-name}/images/download.svg[link="https://bintray.com/aalmiray/kordamp/{project-name}/_latestVersion"] 11 | image:https://img.shields.io/badge/donations-Patreon-orange.svg[link="https://www.patreon.com/user?u=6609318"] 12 | 13 | == Stats Gradle Plugin 14 | 15 | A Gradle plugin for counting lines of code in the same fashion as the 16 | http://grails.org[Grails] stats command. 17 | 18 | == Requirements 19 | 20 | - Gradle 2.x and JDK7. 21 | 22 | == Usage 23 | 24 | The plugin is available from https://bintray.com[Bintray's JCenter]. The latest release 25 | is {plugin-version}. You can use it as follows 26 | 27 | [source,groovy] 28 | [subs="attributes"] 29 | ---- 30 | buildscript { 31 | repositories { 32 | jcenter() 33 | } 34 | dependencies { 35 | classpath 'org.kordamp.gradle:{project-name}:{plugin-version}' 36 | } 37 | } 38 | 39 | apply plugin: 'org.kordamp.gradle.stats' 40 | ---- 41 | 42 | The plugin adds a new task named +stats+. This task is responsible for computing 43 | lines of code. The default configuration is good enough to work with standard 44 | Java or Groovy projects without additional setup. Invoking this task in a plain 45 | Java project yields something like the following output 46 | 47 | [source] 48 | ---- 49 | $ gradle stats 50 | :stats 51 | 52 | +----------------------+-------+-------+ 53 | | Name | Files | LOC | 54 | +----------------------+-------+-------+ 55 | | Java Sources | 1 | 5 | 56 | +----------------------+-------+-------+ 57 | | Totals | 1 | 5 | 58 | +----------------------+-------+-------+ 59 | 60 | ---- 61 | 62 | It's possible to generate an aggregate report when multiple projects are configured. Simply add the following to the 63 | root project 64 | 65 | [source, groovy] 66 | ---- 67 | task aggregateStatsReport(type: org.kordamp.gradle.stats.AggregateStatsReportTask) {} 68 | ---- 69 | 70 | You may define a value for the `projects` property (a collection of project names) if you want desire to limit the number 71 | of projects to be queried for stats. The default setting is to query all subprojects. Note that the `stats` task must have 72 | been called before the aggregate task, such as 73 | 74 | [source] 75 | ---- 76 | $ gradle stats aggregateStatsReport 77 | ---- 78 | 79 | == Configuration 80 | 81 | The following properties can be configured for the +stats+ task 82 | 83 | formats:: List of output formats. Valid values are +xml+, +html+ and +txt+. 84 | reportDir:: Directory where output reports should be placed. default value is 85 | +project.file("${project.buildDir}/reports/stats")+ 86 | counters:: a Map of additional `org.kordamp.gradle.stats.Counter` implementations, keyed by extension. 87 | paths:: Maps of additional source paths that contain sources to be counted. 88 | 89 | The following configuration may be used in a Griffon project for example 90 | 91 | [source,groovy] 92 | ---- 93 | stats { 94 | formats = ['xml', 'html', 'txt'] 95 | paths = [ 96 | model: [name: 'Models', path: 'griffon-app/models'], 97 | view: [name: 'Views', path: 'griffon-app/views'], 98 | controller: [name: 'Controllers', path: 'griffon-app/controllers'], 99 | service: [name: 'Services', path: 'griffon-app/services'], 100 | config: [name: 'Config', path: 'griffon-app/conf'], 101 | lifecycle: [name: 'Lifecycle', path: 'griffon-app/lifecycle'] 102 | ] 103 | } 104 | ---- 105 | 106 | Which may make the +stats+ task output something similar to 107 | 108 | [source,groovy] 109 | ---- 110 | +----------------------+-------+-------+ 111 | | Name | Files | LOC | 112 | +----------------------+-------+-------+ 113 | | Groovy Sources | 4 | 28 | 114 | | Java Sources | 1 | 2 | 115 | | Groovy Test Sources | 1 | 16 | 116 | | Models | 1 | 8 | 117 | | Views | 1 | 24 | 118 | | Controllers | 1 | 10 | 119 | | Config | 1 | 12 | 120 | | Lifecycle | 1 | 16 | 121 | +----------------------+-------+-------+ 122 | | Totals | 11 | 116 | 123 | +----------------------+-------+-------+ 124 | ---- 125 | 126 | You may restrict a path to match an specific file type, such as `java` or any other supported file extension, for example 127 | 128 | [source,groovy] 129 | ---- 130 | stats { 131 | formats = ['xml', 'html', 'txt'] 132 | paths = [ 133 | foo: [name: 'Foos', path: 'src/foo', extension: 'foo'] 134 | ] 135 | } 136 | ---- 137 | 138 | == Supported Extensions 139 | 140 | * java 141 | * groovy 142 | * scala 143 | * kt (Kotlin) 144 | * js 145 | * css 146 | * scss (SASS) 147 | * xml 148 | * html 149 | * fxml (JavaFX FXML) 150 | * properties 151 | * sql 152 | * yaml 153 | 154 | == Supported Paths 155 | 156 | All project SourceSets will be queried when calculating stats, however the following paths have special treatment for 157 | reporting their names: 158 | 159 | * src/test 160 | * src/integration-test 161 | * src/functional-test 162 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | plugins { 18 | id 'groovy' 19 | id 'idea' 20 | id 'maven-publish' 21 | id 'java-gradle-plugin' 22 | id 'com.jfrog.bintray' version '1.8.0' 23 | id 'net.nemerosa.versioning' version '2.6.1' 24 | id 'com.github.ben-manes.versions' version '0.17.0' 25 | id 'com.gradle.plugin-publish' version '0.9.9' 26 | id 'com.github.hierynomus.license' version '0.11.0' 27 | id 'com.github.kt3k.coveralls' version '2.8.2' 28 | } 29 | 30 | apply from: 'gradle/publishing.gradle' 31 | apply from: 'gradle/code-coverage.gradle' 32 | apply from: 'gradle/code-quality.gradle' 33 | 34 | repositories { 35 | jcenter() 36 | } 37 | 38 | dependencies { 39 | compile gradleApi() 40 | testCompile 'junit:junit:4.12' 41 | testCompile('org.spockframework:spock-core:1.1-groovy-2.4') { 42 | exclude group: 'org.codehaus.groovy', module: 'groovy-all' 43 | } 44 | } 45 | 46 | tasks.withType(JavaCompile) { 47 | sourceCompatibility = 1.6 48 | targetCompatibility = 1.6 49 | } 50 | 51 | tasks.withType(GroovyCompile) { 52 | sourceCompatibility = 1.6 53 | targetCompatibility = 1.6 54 | } 55 | 56 | javadoc { 57 | excludes = ['**/*.html', 'META-INF/**'] 58 | 59 | options.use = true 60 | options.splitIndex = true 61 | options.encoding = 'UTF-8' 62 | options.author = true 63 | options.version = true 64 | options.windowTitle = "$project.name $project.version API" 65 | options.docTitle = "$project.name $project.version API" 66 | options.links = ['http://docs.oracle.com/javase/7/docs/api/'] 67 | } 68 | 69 | task sourcesJar(type: Jar) { 70 | group 'Build' 71 | description 'An archive of the source code' 72 | classifier 'sources' 73 | from sourceSets.main.allSource 74 | } 75 | 76 | task javadocJar(type: Jar) { 77 | group 'Build' 78 | description 'An archive of the javadoc' 79 | classifier 'javadoc' 80 | from javadoc.destinationDir 81 | } 82 | 83 | jar.finalizedBy sourcesJar 84 | jar.finalizedBy javadocJar 85 | 86 | artifacts { 87 | sourcesJar 88 | javadocJar 89 | } 90 | 91 | task publishRelease(dependsOn: [bintrayUpload, publishPlugins]) {} 92 | -------------------------------------------------------------------------------- /config/HEADER: -------------------------------------------------------------------------------- 1 | Copyright ${year} the original author or authors. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /config/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /config/codenarc/codenarc.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | ruleset { 18 | ruleset('rulesets/basic.xml') { 19 | exclude 'EmptyCatchBlock' 20 | exclude 'EmptyMethod' 21 | } 22 | ruleset('rulesets/imports.xml') { 23 | exclude 'MisorderedStaticImports' 24 | } 25 | ruleset('rulesets/naming.xml') { 26 | exclude 'PropertyName' 27 | 'ClassName' { 28 | regex = '^[A-Z][a-zA-Z0-9]*$' 29 | } 30 | 'FieldName' { 31 | finalRegex = '^_?[a-z][a-zA-Z0-9]*$' 32 | staticFinalRegex = '^[A-Z][A-Z_0-9]*$' 33 | } 34 | 'MethodName' { 35 | regex = '^[a-z][a-zA-Z0-9_]*$' 36 | } 37 | 'VariableName' { 38 | finalRegex = '^_?[a-z][a-zA-Z0-9]*$' 39 | } 40 | } 41 | ruleset('rulesets/unused.xml') 42 | ruleset('rulesets/exceptions.xml') 43 | // ruleset('rulesets/logging.xml') 44 | ruleset('rulesets/braces.xml') { 45 | exclude 'IfStatementBraces' 46 | } 47 | ruleset('rulesets/size.xml') 48 | ruleset('rulesets/junit.xml') 49 | ruleset('rulesets/unnecessary.xml') 50 | ruleset('rulesets/dry.xml') 51 | ruleset('rulesets/design.xml') 52 | } 53 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version = 0.2.2 2 | group = org.kordamp.gradle 3 | 4 | project_vendor = aalmiray 5 | project_description = LOC counter 6 | project_url = https://github.com/aalmiray/stats-gradle-plugin 7 | project_scm = https://github.com/aalmiray/stats-gradle-plugin 8 | project_issues_url = https://github.com/aalmiray/stats-gradle-plugin/issues 9 | project_bintray_repo = kordamp 10 | project_bintray_org = aalmiray 11 | -------------------------------------------------------------------------------- /gradle/code-coverage.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | apply plugin: 'jacoco' 18 | 19 | jacoco { 20 | toolVersion = '0.7.9' 21 | } 22 | 23 | jacocoTestReport { 24 | group = "Reporting" 25 | description = "Generate Jacoco coverage reports after running tests." 26 | additionalSourceDirs = project.files(sourceSets.main.allSource.srcDirs) 27 | sourceDirectories = project.files(sourceSets.main.allSource.srcDirs) 28 | classDirectories = project.files(sourceSets.main.output) 29 | reports { 30 | xml.enabled = true 31 | csv.enabled = false 32 | html.enabled = true 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /gradle/code-quality.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | license { 18 | header = rootProject.file('config/HEADER') 19 | strictCheck = true 20 | ignoreFailures = true 21 | mapping { 22 | java = 'SLASHSTAR_STYLE' 23 | groovy = 'SLASHSTAR_STYLE' 24 | } 25 | ext.year = '2014-2017' 26 | } 27 | 28 | licenseTest { 29 | source -= sourceSets.test.resources 30 | } 31 | -------------------------------------------------------------------------------- /gradle/publishing.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.text.SimpleDateFormat 18 | 19 | Date buildTimeAndDate = new Date() 20 | ext { 21 | buildDate = new SimpleDateFormat('yyyy-MM-dd').format(buildTimeAndDate) 22 | buildTime = new SimpleDateFormat('HH:mm:ss.SSSZ').format(buildTimeAndDate) 23 | } 24 | 25 | apply plugin: 'maven-publish' 26 | apply plugin: 'com.jfrog.bintray' 27 | 28 | jar { 29 | manifest { 30 | attributes( 31 | 'Built-By': System.properties['user.name'], 32 | 'Created-By': System.properties['java.version'] + ' (' + System.properties['java.vendor'] + ' ' + System.properties["java.vm.version"] + ')', 33 | 'Build-Date': project.buildDate, 34 | 'Build-Time': project.buildTime, 35 | 'Specification-Title': project.name, 36 | 'Specification-Version': project.version, 37 | 'Specification-Vendor': project.project_vendor, 38 | 'Implementation-Title': project.name, 39 | 'Implementation-Version': project.version, 40 | 'Implementation-Vendor': project.project_vendor 41 | ) 42 | } 43 | } 44 | 45 | def pomConfig = { 46 | name project.name 47 | description project.project_description 48 | url project.project_url 49 | inceptionYear '2014' 50 | licenses { 51 | license([:]) { 52 | name 'The Apache Software License, Version 2.0' 53 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 54 | distribution 'repo' 55 | } 56 | } 57 | scm { 58 | url project.project_scm 59 | } 60 | developers { 61 | [ 62 | aalmiray : 'Andres Almiray' 63 | ].each { devId, devName -> 64 | developer { 65 | id devId 66 | name devName 67 | roles { 68 | role 'Developer' 69 | } 70 | } 71 | } 72 | } 73 | } 74 | 75 | publishing { 76 | publications { 77 | mavenCustom(MavenPublication) { 78 | from components.java 79 | artifact sourcesJar 80 | 81 | pom.withXml { 82 | asNode().children().last() + pomConfig 83 | asNode().appendNode('description', project.project_description) 84 | } 85 | } 86 | } 87 | } 88 | 89 | if (!project.hasProperty('bintrayUsername')) ext.bintrayUsername = 'invalid' 90 | if (!project.hasProperty('bintrayApiKey')) ext.bintrayApiKey = 'invalid' 91 | 92 | bintray { 93 | user = project.bintrayUsername 94 | key = project.bintrayApiKey 95 | publications = ['mavenCustom'] 96 | pkg { 97 | repo = project.project_bintray_repo 98 | userOrg = project.project_bintray_org 99 | name = project.name 100 | desc = project.project_description 101 | licenses = ['Apache-2.0'] 102 | labels = ['gradle', 'plugin'] 103 | websiteUrl = project.project_url 104 | issueTrackerUrl = project.project_issues_url 105 | vcsUrl = project.project_scm 106 | publicDownloadNumbers = true 107 | version { 108 | vcsTag = project.version 109 | attributes = [ 110 | 'gradle-plugin': 'org.kordamp.gradle.stats:org.kordamp.gradle:stats-gradle-plugin' 111 | ] 112 | } 113 | } 114 | } 115 | 116 | pluginBundle { 117 | website = project.project_url 118 | vcsUrl = project.project_scm 119 | description = project.project_description 120 | tags = ['stats'] 121 | 122 | plugins { 123 | statsPlugin { 124 | id = 'org.kordamp.gradle.stats' 125 | displayName = 'Stats Gradle Plugin' 126 | } 127 | } 128 | 129 | mavenCoordinates { 130 | groupId = project.group 131 | artifactId = project.name 132 | version = project.version 133 | } 134 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/AggregateStatsReportTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | import groovy.xml.MarkupBuilder 19 | import org.gradle.api.DefaultTask 20 | import org.gradle.api.Project 21 | import org.gradle.api.tasks.Input 22 | import org.gradle.api.tasks.Optional 23 | import org.gradle.api.tasks.TaskAction 24 | 25 | /** 26 | * @author Andres Almiray 27 | */ 28 | class AggregateStatsReportTask extends DefaultTask { 29 | @Optional @Input Collection projects = [] 30 | @Optional @Input List formats = [] 31 | @Optional @Input File reportDir 32 | 33 | File xmlReport 34 | 35 | private static final String XML = 'xml' 36 | private static final String HTML = 'html' 37 | private static final String TXT = 'txt' 38 | 39 | AggregateStatsReportTask() { 40 | reportDir = project.file("${project.buildDir}/reports/stats") 41 | xmlReport = project.file("${reportDir}/${project.name}-all.xml") 42 | projects = project.subprojects.name 43 | } 44 | 45 | @TaskAction 46 | void computeAggregate() { 47 | 48 | Map> stats = [:] 49 | 50 | projects.each { name -> 51 | Project p = project.project(name) 52 | StatsTask t = p.tasks.findByName('stats') 53 | if (!t || !t.xmlReport.exists()) return 54 | def xml = new XmlSlurper().parse(t.xmlReport) 55 | xml.category.each { category -> 56 | String n = category.@name.text() ? category.@name.text() : 'Totals' 57 | Map map = stats.get(n, [fileCount: 0, locCount: 0]) 58 | map.fileCount += category.fileCount.text().toInteger() 59 | map.locCount += category.loc.text().toInteger() 60 | } 61 | } 62 | 63 | Map totals = stats.remove('Totals') 64 | stats = stats.sort { it.key } 65 | 66 | if (stats) { 67 | int max = 0 68 | stats.keySet().each { max = Math.max(max, it.size()) } 69 | max = Math.max(max, 22) 70 | 71 | output(stats, max, totals.fileCount.toString(), totals.locCount.toString(), new PrintWriter(System.out)) 72 | xmlOutput(stats, totals.fileCount.toString(), totals.locCount.toString()) 73 | if (HTML in formats) htmlOutput(stats, totals.fileCount.toString(), totals.locCount.toString()) 74 | if (TXT in formats) output(stats, max, totals.fileCount.toString(), totals.locCount.toString(), new PrintWriter(getOutputFile(TXT))) 75 | } 76 | } 77 | 78 | private void output(Map> stats, int max, String totalFiles, String totalLOC, Writer out) { 79 | int padFiles = Math.max(totalFiles.toString().length(), 7) 80 | int padLocs = Math.max(totalLOC.toString().length(), 7) 81 | 82 | out.println ' +-' + ('-' * max) + '-+---------+---------+' 83 | out.println ' | ' + 'Name'.padRight(max, ' ') + ' | '+ 84 | 'Files'.padLeft(padFiles, ' ') + ' | ' + 85 | 'LOC'.padLeft(padLocs, ' ') + ' |' 86 | out.println ' +-' + ('-' * max) + '-+---------+---------+' 87 | 88 | stats.each { category, info -> 89 | out.println ' | ' + 90 | category.padRight(max, ' ') + ' | ' + 91 | info.fileCount.toString().padLeft(padFiles, ' ') + ' | ' + 92 | info.locCount.toString().padLeft(padLocs, ' ') + ' |' 93 | } 94 | 95 | out.println ' +-' + ('-' * max) + '-+---------+---------+' 96 | out.println ' | ' + 'Totals'.padRight(max, ' ') + ' | ' + totalFiles.padLeft(padFiles, ' ') + ' | ' + totalLOC.padLeft(padLocs, ' ') + ' |' 97 | out.println ' +-' + ('-' * max) + '-+---------+---------+\n' 98 | 99 | out.flush() 100 | } 101 | 102 | private void xmlOutput(Map> stats, String totalFiles, String totalLOC) { 103 | new MarkupBuilder(new FileWriter(getOutputFile(XML))).stats { 104 | stats.each { c, info -> 105 | category(name: c) { 106 | fileCount(info.fileCount.toString()) 107 | loc(info.locCount.toString()) 108 | } 109 | } 110 | category { 111 | name('Total') 112 | fileCount(totalFiles) 113 | loc(totalLOC) 114 | } 115 | } 116 | } 117 | 118 | private void htmlOutput(Map> stats, String totalFiles, String totalLOC) { 119 | int i = 0 120 | new MarkupBuilder(new FileWriter(getOutputFile(HTML))).html { 121 | table(border: 1) { 122 | tr { 123 | th('Name') 124 | th(align:'right', 'Files') 125 | th(align:'right', 'LOC') 126 | } 127 | stats.each { type, info -> 128 | tr(style: (i++) % 2 ? 'background-color:lightblue' : 'background-color:FFF') { 129 | td(type) 130 | td(align:'right', info.fileCount.toString()) 131 | td(align:'right', info.locCount.toString()) 132 | } 133 | } 134 | tr(style: 'background-color:lightgreen') { 135 | b { 136 | td('Total') 137 | td(align:'right', totalFiles) 138 | td(align:'right', totalLOC) 139 | } 140 | } 141 | } 142 | } 143 | } 144 | 145 | private getOutputFile(String suffix) { 146 | reportDir.mkdirs() 147 | new File(reportDir, project.name + '-all.' + suffix) 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/Counter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | interface Counter { 22 | String EMPTY = /^\s*$/ 23 | String SLASH_SLASH = /^\s*\/\/.*/ 24 | String SLASH_STAR_STAR_SLASH = /^(.*)\/\*(.*)\*\/(.*)$/ 25 | 26 | int count(File file) 27 | } 28 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/CssCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class CssCounter implements Counter { 22 | @Override 23 | int count(File file) { 24 | def loc = 0 25 | def comment = 0 26 | file.eachLine { line -> 27 | if (!line.trim().length() || line ==~ EMPTY) return 28 | 29 | def m = line =~ SLASH_STAR_STAR_SLASH 30 | if (m.count && m[0][1] ==~ EMPTY && m[0][3] ==~ EMPTY) return 31 | int open = line.indexOf('/*') 32 | int close = line.indexOf('*/') 33 | if (open != -1 && (close - open) <= 1) comment++ 34 | else if (close != -1 && comment) { 35 | comment-- 36 | if (!comment) return 37 | } 38 | 39 | if (!comment) loc++ 40 | } 41 | 42 | loc 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/HashCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class HashCounter implements Counter { 22 | String HASH = /^\s*#\s?.*/ 23 | 24 | @Override 25 | int count(File file) { 26 | def loc = 0 27 | file.eachLine { line -> 28 | if (!(line.trim().length()) || line ==~ EMPTY || line ==~ HASH) return 29 | loc++ 30 | } 31 | 32 | loc 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/JavaCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class JavaCounter implements Counter { 22 | @Override 23 | int count(File file) { 24 | def loc = 0 25 | def comment = 0 26 | file.eachLine { line -> 27 | if (!line.trim().length() || line ==~ EMPTY) return 28 | else if (line ==~ SLASH_SLASH) return 29 | 30 | def m = line =~ SLASH_STAR_STAR_SLASH 31 | if (m.count && m[0][1] ==~ EMPTY && m[0][3] ==~ EMPTY) return 32 | int open = line.indexOf('/*') 33 | int close = line.indexOf('*/') 34 | if (open != -1 && (close - open) <= 1) comment++ 35 | else if (close != -1 && comment) { 36 | comment-- 37 | if (!comment) return 38 | } 39 | 40 | if (!comment) loc++ 41 | } 42 | 43 | loc 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/PropertiesCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class PropertiesCounter implements Counter { 22 | @Override 23 | int count(File file) { 24 | def loc = 0 25 | file.eachLine { line -> 26 | if (!(line.trim().length()) || line ==~ EMPTY || line.trim().startsWith('#')) return 27 | loc++ 28 | } 29 | 30 | loc 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/SemiColonCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class SemiColonCounter implements Counter { 22 | String SEMICOLON = /^\s*;.*/ 23 | 24 | @Override 25 | int count(File file) { 26 | def loc = 0 27 | file.eachLine { line -> 28 | if (!(line.trim().length()) || line ==~ EMPTY || line ==~ SEMICOLON) return 29 | loc++ 30 | } 31 | 32 | loc 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/SqlCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class SqlCounter implements Counter { 22 | String DASH_DASH = /^\s*--.*/ 23 | 24 | @Override 25 | int count(File file) { 26 | def loc = 0 27 | def comment = 0 28 | file.eachLine { line -> 29 | if (!line.trim().length() || line ==~ EMPTY) return 30 | else if (line ==~ DASH_DASH) return 31 | 32 | def m = line =~ SLASH_STAR_STAR_SLASH 33 | if (m.count && m[0][1] ==~ EMPTY && m[0][3] ==~ EMPTY) return 34 | int open = line.indexOf('/*') 35 | int close = line.indexOf('*/') 36 | if (open != -1 && (close - open) <= 1) comment++ 37 | else if (close != -1 && comment) { 38 | comment-- 39 | if (!comment) return 40 | } 41 | 42 | if (!comment) loc++ 43 | } 44 | 45 | loc 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/StatsPlugin.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | import org.gradle.api.Plugin 19 | import org.gradle.api.Project 20 | 21 | /** 22 | * @author Andres Almiray 23 | */ 24 | class StatsPlugin implements Plugin { 25 | static final String STATS = 'stats' 26 | 27 | void apply(Project project) { 28 | project.apply(plugin: 'base') 29 | 30 | project.task(STATS, type: StatsTask, group: 'Build', 31 | description: 'Counts source lines') 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/StatsTask.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | import groovy.xml.MarkupBuilder 19 | import org.gradle.api.DefaultTask 20 | import org.gradle.api.tasks.Input 21 | import org.gradle.api.tasks.Optional 22 | import org.gradle.api.tasks.TaskAction 23 | 24 | /** 25 | * @author Andres Almiray 26 | */ 27 | class StatsTask extends DefaultTask { 28 | @Optional @Input Map counters = [:] 29 | @Optional @Input Map> paths = [:] 30 | @Optional @Input List formats = [] 31 | @Optional @Input File reportDir 32 | 33 | File xmlReport 34 | 35 | int totalFiles = 0 36 | int totalLOC = 0 37 | 38 | private static final String XML = 'xml' 39 | private static final String HTML = 'html' 40 | private static final String TXT = 'txt' 41 | 42 | StatsTask() { 43 | reportDir = project.file("${project.buildDir}/reports/stats") 44 | xmlReport = project.file("${reportDir}/${project.name}.xml") 45 | } 46 | 47 | @TaskAction 48 | void computeLoc() { 49 | Map counterInstances = resolveCounterInstances() 50 | Map> basePaths = [:] 51 | 52 | [ 53 | java : 'Java', 54 | groovy : 'Groovy', 55 | scala : 'Scala', 56 | kt : 'Kotlin', 57 | js : 'Javascript', 58 | css : 'CSS', 59 | scss : 'SASS', 60 | xml : 'XML', 61 | html : 'HTML', 62 | fxml : 'FXML', 63 | properties: 'Properties', 64 | sql : 'SQL', 65 | yaml : 'YAML', 66 | clojure : 'Clojure' 67 | ].each { extension, name -> 68 | ['test', 'integration-test', 'functional-test'].each { source -> 69 | String classifier = StatsTask.getPropertyNameForLowerCaseHyphenSeparatedName(source) 70 | basePaths[classifier + extension.capitalize()] = [name: name + ' ' + StatsTask.getNaturalName(classifier) + ' Sources', path: 'src/' + source, extension: extension] 71 | } 72 | } 73 | 74 | Map merged = [:] 75 | merged.putAll(basePaths) 76 | merged.putAll(paths) 77 | 78 | merged.java = [name: 'Java Sources', path: '.*', extension: 'java'] 79 | merged.groovy = [name: 'Groovy Sources', path: '.*', extension: 'groovy'] 80 | merged.scala = [name: 'Scala Sources', path: '.*', extension: 'scala'] 81 | merged.kt = [name: 'Kotlin Sources', path: '.*', extension: 'kt'] 82 | merged.js = [name: 'Javascript Sources', path: '.*', extension: 'js'] 83 | merged.css = [name: 'CSS Sources', path: '.*', extension: 'css'] 84 | merged.scss = [name: 'SASS Sources', path: '.*', extension: 'scss'] 85 | merged.xml = [name: 'XML Sources', path: '.*', extension: 'xml'] 86 | merged.html = [name: 'HTML Sources', path: '.*', extension: 'html'] 87 | merged.fxml = [name: 'FXML Sources', path: '.*', extension: 'fxml'] 88 | merged.properties = [name: 'Properties', path: '.*', extension: 'properties'] 89 | merged.sql = [name: 'SQL', path: '.*', extension: 'sql'] 90 | merged.yaml = [name: 'Yaml', path: '.*', extension: 'yaml'] 91 | merged.clj = [name: 'Clojure', path: '.*', extension: 'clj'] 92 | 93 | resolveSourceSets().each { sourceSet -> 94 | sourceSet.allSource.srcDirs.each { File dir -> 95 | if (!dir.exists()) return 96 | dir.eachFileRecurse { File file -> 97 | if (file.file) { 98 | String extension = StatsTask.getFilenameExtension(file.name) 99 | Map map = merged.find { file.absolutePath =~ it.value.path && !it.value.extension }?.value 100 | if (!map) map = merged.find { 101 | file.absolutePath =~ it.value.path && extension == it.value.extension 102 | }?.value 103 | if (!map) map = merged.find { file.absolutePath =~ it.value.path }?.value 104 | if (!map || (map.extension && extension != map.extension)) return 105 | if (counterInstances.containsKey(extension)) { 106 | StatsTask.countLines(map, counterInstances[extension], file) 107 | } 108 | } 109 | } 110 | } 111 | } 112 | 113 | merged.each { type, info -> 114 | if (info.files) { 115 | totalFiles += info.files 116 | totalLOC += info.lines 117 | } 118 | } 119 | 120 | if (totalFiles) { 121 | int max = 0 122 | merged.values().each { if (it.files) max = Math.max(max, it.name.size()) } 123 | max = Math.max(max, 22) 124 | merged = merged.sort { it.value.name } 125 | 126 | output(merged, max, totalFiles.toString(), totalLOC.toString(), new PrintWriter(System.out)) 127 | xmlOutput(merged, totalFiles.toString(), totalLOC.toString()) 128 | if (HTML in formats) htmlOutput(merged, totalFiles.toString(), totalLOC.toString()) 129 | if (TXT in formats) output(merged, max, totalFiles.toString(), totalLOC.toString(), new PrintWriter(getOutputFile(TXT))) 130 | } 131 | } 132 | 133 | private resolveSourceSets() { 134 | if (project.plugins.hasPlugin('com.android.library')) { 135 | project.android.sourceSets 136 | } else { 137 | project.sourceSets 138 | } 139 | } 140 | 141 | private static void countLines(Map work, Counter counter, File file) { 142 | int numFiles = work.get('files', 0) 143 | work.files = ++numFiles 144 | int lines = counter.count(file) 145 | int numLines = work.get('lines', 0) 146 | work.lines = numLines + lines 147 | } 148 | 149 | private Map resolveCounterInstances() { 150 | Map instances = [:] 151 | counters.collect { key, classname -> 152 | instances[key] = Class.forName(classname).newInstance() 153 | } 154 | 155 | if (!instances.java) instances.java = new JavaCounter() 156 | if (!instances.groovy) instances.groovy = new JavaCounter() 157 | if (!instances.js) instances.js = new JavaCounter() 158 | if (!instances.scala) instances.scala = new JavaCounter() 159 | if (!instances.kt) instances.kt = new JavaCounter() 160 | if (!instances.css) instances.css = new CssCounter() 161 | if (!instances.scss) instances.scss = new JavaCounter() 162 | if (!instances.xml) instances.xml = new XmlCounter() 163 | if (!instances.html) instances.html = new XmlCounter() 164 | if (!instances.fxml) instances.fxml = new XmlCounter() 165 | if (!instances.properties) instances.properties = new PropertiesCounter() 166 | if (!instances.sql) instances.sql = new SqlCounter() 167 | if (!instances.yaml) instances.yaml = new HashCounter() 168 | if (!instances.clj) instances.clj = new SemiColonCounter() 169 | 170 | instances 171 | } 172 | 173 | private void output(Map> work, int max, String totalFiles, String totalLOC, Writer out) { 174 | int padFiles = Math.max(totalFiles.toString().length(), 6) 175 | int padLocs = Math.max(totalLOC.toString().length(), 6) 176 | 177 | out.println ' +-' + ('-' * max) + '-+--------+--------+' 178 | out.println ' | ' + 'Name'.padRight(max, ' ') + ' | '+ 179 | 'Files'.padLeft(padFiles, ' ') + ' | ' + 180 | 'LOC'.padLeft(padLocs, ' ') + ' |' 181 | out.println ' +-' + ('-' * max) + '-+--------+--------+' 182 | 183 | work.each { type, info -> 184 | if (info.files) { 185 | out.println ' | ' + 186 | info.name.padRight(max, ' ') + ' | ' + 187 | info.files.toString().padLeft(padFiles, ' ') + ' | ' + 188 | info.lines.toString().padLeft(padLocs, ' ') + ' |' 189 | } 190 | } 191 | 192 | out.println ' +-' + ('-' * max) + '-+--------+--------+' 193 | out.println ' | ' + 'Totals'.padRight(max, ' ') + ' | ' + totalFiles.padLeft(padFiles, ' ') + ' | ' + totalLOC.padLeft(padLocs, ' ') + ' |' 194 | out.println ' +-' + ('-' * max) + '-+--------+--------+\n' 195 | 196 | out.flush() 197 | } 198 | 199 | private void xmlOutput(Map> work, String totalFiles, String totalLOC) { 200 | new MarkupBuilder(new FileWriter(getOutputFile(XML))).stats { 201 | work.each { type, info -> 202 | if (info.files) { 203 | category(name: info.name) { 204 | fileCount(info.files.toString()) 205 | loc(info.lines.toString()) 206 | } 207 | } 208 | } 209 | category { 210 | name('Total') 211 | fileCount(totalFiles) 212 | loc(totalLOC) 213 | } 214 | } 215 | } 216 | 217 | private void htmlOutput(Map> work, String totalFiles, String totalLOC) { 218 | int i = 0 219 | new MarkupBuilder(new FileWriter(getOutputFile(HTML))).html { 220 | table(border: 1) { 221 | tr { 222 | th('Name') 223 | th(align:'right', 'Files') 224 | th(align:'right', 'LOC') 225 | } 226 | work.each { type, info -> 227 | if (info.files) { 228 | tr(style: (i++) % 2 ? 'background-color:lightblue' : 'background-color:FFF') { 229 | td(info.name) 230 | td(align:'right', info.files.toString()) 231 | td(align:'right', info.lines.toString()) 232 | } 233 | } 234 | } 235 | tr(style: 'background-color:lightgreen') { 236 | b { 237 | td('Total') 238 | td(align:'right', totalFiles) 239 | td(align:'right', totalLOC) 240 | } 241 | } 242 | } 243 | } 244 | } 245 | 246 | private getOutputFile(String suffix) { 247 | reportDir.mkdirs() 248 | new File(reportDir, project.name + '.' + suffix) 249 | } 250 | 251 | private static String getFilenameExtension(String path) { 252 | if (path == null) { 253 | return null; 254 | } 255 | int extIndex = path.lastIndexOf("."); 256 | if (extIndex == -1) { 257 | return null; 258 | } 259 | int folderIndex = path.lastIndexOf("/"); 260 | if (folderIndex > extIndex) { 261 | return null; 262 | } 263 | return path.substring(extIndex + 1); 264 | } 265 | 266 | private static String getNaturalName(String name) { 267 | name = getShortName(name); 268 | if (isBlank(name)) return name; 269 | List words = new ArrayList<>(); 270 | int i = 0; 271 | char[] chars = name.toCharArray(); 272 | for (char c : chars) { 273 | String w; 274 | if (i >= words.size()) { 275 | w = ""; 276 | words.add(i, w); 277 | } else { 278 | w = words.get(i); 279 | } 280 | 281 | if (Character.isLowerCase(c) || Character.isDigit(c)) { 282 | if (Character.isLowerCase(c) && w.length() == 0) { 283 | c = Character.toUpperCase(c); 284 | } else if (w.length() > 1 && Character.isUpperCase(w.charAt(w.length() - 1))) { 285 | w = ""; 286 | words.add(++i, w); 287 | } 288 | 289 | words.set(i, w + c); 290 | } else if (Character.isUpperCase(c)) { 291 | if ((i == 0 && w.length() == 0) || Character.isUpperCase(w.charAt(w.length() - 1))) { 292 | words.set(i, w + c); 293 | } else { 294 | words.add(++i, String.valueOf(c)); 295 | } 296 | } 297 | } 298 | 299 | StringBuilder buf = new StringBuilder(); 300 | for (Iterator j = words.iterator(); j.hasNext();) { 301 | String word = j.next(); 302 | buf.append(word); 303 | if (j.hasNext()) { 304 | buf.append(' '); 305 | } 306 | } 307 | return buf.toString(); 308 | } 309 | 310 | private static String getShortName(String className) { 311 | if (isBlank(className)) return className; 312 | int i = className.lastIndexOf("."); 313 | if (i > -1) { 314 | className = className.substring(i + 1, className.length()); 315 | } 316 | return className; 317 | } 318 | 319 | private static boolean isBlank(String str) { 320 | if (str == null || str.length() == 0) { 321 | return true; 322 | } 323 | for (char c : str.toCharArray()) { 324 | if (!Character.isWhitespace(c)) { 325 | return false; 326 | } 327 | } 328 | 329 | return true; 330 | } 331 | 332 | private static String getPropertyNameForLowerCaseHyphenSeparatedName(String name) { 333 | return getPropertyName(getClassNameForLowerCaseHyphenSeparatedName(name)); 334 | } 335 | 336 | private static String getClassNameForLowerCaseHyphenSeparatedName(String name) { 337 | // Handle null and empty strings. 338 | if (isBlank(name)) return name; 339 | 340 | if (name.indexOf('-') > -1) { 341 | StringBuilder buf = new StringBuilder(); 342 | String[] tokens = name.split("-"); 343 | for (String token : tokens) { 344 | if (token == null || token.length() == 0) continue; 345 | buf.append(capitalize(token)); 346 | } 347 | return buf.toString(); 348 | } 349 | 350 | return capitalize(name); 351 | } 352 | 353 | private static String capitalize(String str) { 354 | if (isBlank(str)) return str; 355 | if (str.length() == 1) return str.toUpperCase(); 356 | return str.substring(0, 1).toUpperCase(Locale.ENGLISH) + str.substring(1); 357 | } 358 | 359 | private static String getPropertyName(String name) { 360 | if (isBlank(name)) return name; 361 | // Strip any package from the name. 362 | int pos = name.lastIndexOf('.'); 363 | if (pos != -1) { 364 | name = name.substring(pos + 1); 365 | } 366 | 367 | // Check whether the name begins with two upper case letters. 368 | if (name.length() > 1 && Character.isUpperCase(name.charAt(0)) && Character.isUpperCase(name.charAt(1))) { 369 | return name; 370 | } 371 | 372 | String propertyName = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1); 373 | if (propertyName.indexOf(' ') > -1) { 374 | propertyName = propertyName.replaceAll("\\s", ""); 375 | } 376 | return propertyName; 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /src/main/groovy/org/kordamp/gradle/stats/XmlCounter.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | /** 19 | * @author Andres Almiray 20 | */ 21 | class XmlCounter implements Counter { 22 | String OPEN_CARET_CLOSE_CARET = /^(.*)(.*)$/ 23 | 24 | @Override 25 | int count(File file) { 26 | def loc = 0 27 | def comment = 0 28 | file.eachLine { line -> 29 | if (!line.trim().length() || line ==~ EMPTY) return 30 | 31 | def m = line =~ OPEN_CARET_CLOSE_CARET 32 | if (m.count && m[0][1] ==~ EMPTY && m[0][3] ==~ EMPTY) return 33 | int open = line.indexOf('') 35 | 36 | if (open != -1 && (close - open) <= 1) comment++ 37 | else if (close != -1 && comment) { 38 | comment-- 39 | if (!comment) return 40 | } 41 | 42 | if (!comment) loc++ 43 | } 44 | 45 | loc 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/gradle-plugins/org.kordamp.gradle.stats.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2014-2017 the original author or authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | implementation-class=org.kordamp.gradle.stats.StatsPlugin -------------------------------------------------------------------------------- /src/test/groovy/org/kordamp/gradle/stats/StatsPluginSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | import org.gradle.api.Project 19 | import org.gradle.api.Task 20 | import org.gradle.testfixtures.ProjectBuilder 21 | import spock.lang.Specification 22 | 23 | /** 24 | * @author Andres Almiray 25 | */ 26 | class StatsPluginSpec extends Specification { 27 | private static final String STATS = 'stats' 28 | 29 | Project project 30 | 31 | def setup() { 32 | project = ProjectBuilder.builder().build() 33 | } 34 | 35 | @SuppressWarnings('MethodName') 36 | def "Applies plugin and checks default setup"() { 37 | expect: 38 | project.tasks.findByName(STATS) == null 39 | 40 | when: 41 | project.apply plugin: StatsPlugin 42 | 43 | then: 44 | Task statsTask = project.tasks.findByName(STATS) 45 | statsTask != null 46 | statsTask.group == 'Build' 47 | statsTask.reportDir == project.file("${project.buildDir}/reports/stats") 48 | 49 | project.tasks.findByName('clean') != null 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/groovy/org/kordamp/gradle/stats/StatsTaskSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.kordamp.gradle.stats 17 | 18 | import org.gradle.api.Project 19 | import org.gradle.api.plugins.GroovyPlugin 20 | import org.gradle.api.plugins.JavaPlugin 21 | import org.gradle.api.plugins.scala.ScalaPlugin 22 | import org.gradle.testfixtures.ProjectBuilder 23 | import spock.lang.Specification 24 | 25 | /** 26 | * @author Andres Almiray 27 | */ 28 | @SuppressWarnings('MethodName') 29 | class StatsTaskSpec extends Specification { 30 | private static final String STATS = 'stats' 31 | 32 | Project project 33 | File testRootDir 34 | 35 | void "Calculate stats on basic Java project"() { 36 | given: 37 | testRootDir = new File('src/test/projects/basic_java') 38 | project = ProjectBuilder.builder().withName('test') 39 | .withProjectDir(testRootDir).build() 40 | project.apply(plugin: JavaPlugin) 41 | project.apply(plugin: StatsPlugin) 42 | StatsTask task = project.tasks.findByName(STATS) 43 | 44 | when: 45 | task.computeLoc() 46 | 47 | then: 48 | 2 == task.totalFiles 49 | 13 == task.totalLOC 50 | } 51 | 52 | void "Calculate stats on basic Scala project"() { 53 | given: 54 | testRootDir = new File('src/test/projects/basic_scala') 55 | project = ProjectBuilder.builder().withName('test') 56 | .withProjectDir(testRootDir).build() 57 | project.apply(plugin: ScalaPlugin) 58 | project.apply(plugin: StatsPlugin) 59 | StatsTask task = project.tasks.findByName(STATS) 60 | 61 | when: 62 | task.computeLoc() 63 | 64 | then: 65 | 2 == task.totalFiles 66 | 13 == task.totalLOC 67 | } 68 | 69 | void "Calculate stats on basic project"() { 70 | given: 71 | testRootDir = new File('src/test/projects/basic_all') 72 | project = ProjectBuilder.builder().withName('test') 73 | .withProjectDir(testRootDir).build() 74 | project.apply(plugin: JavaPlugin) 75 | project.apply(plugin: StatsPlugin) 76 | StatsTask task = project.tasks.findByName(STATS) 77 | 78 | when: 79 | task.computeLoc() 80 | 81 | then: 82 | 12 == task.totalFiles 83 | 44 == task.totalLOC 84 | } 85 | 86 | void "Calculate stats on basic Griffon project"() { 87 | given: 88 | testRootDir = new File('src/test/projects/basic_griffon') 89 | project = ProjectBuilder.builder().withName('test') 90 | .withProjectDir(testRootDir).build() 91 | project.apply(plugin: GroovyPlugin) 92 | project.apply(plugin: StatsPlugin) 93 | project.sourceSets.main.groovy.srcDirs = [ 94 | 'griffon-app/conf', 95 | 'griffon-app/controllers', 96 | 'griffon-app/models', 97 | 'griffon-app/views', 98 | 'griffon-app/services', 99 | 'griffon-app/lifecycle', 100 | 'src/main/groovy' 101 | ] 102 | project.sourceSets.main.resources.srcDirs = [ 103 | 'griffon-app/resources', 104 | 'griffon-app/i18n', 105 | 'src/main/resources' 106 | ] 107 | project.sourceSets.maybeCreate('integrationTest').groovy.srcDirs = [ 108 | 'src/integration-test/groovy' 109 | ] 110 | 111 | StatsTask task = project.tasks.findByName(STATS) 112 | task.paths = [ 113 | model : [name: 'Models', path: 'griffon-app/models'], 114 | view : [name: 'Views', path: 'griffon-app/views'], 115 | controller: [name: 'Controllers', path: 'griffon-app/controllers'], 116 | service : [name: 'Services', path: 'griffon-app/services'], 117 | config : [name: 'Config', path: 'griffon-app/conf'], 118 | lifecycle : [name: 'Lifecycle', path: 'griffon-app/lifecycle'] 119 | ] 120 | 121 | when: 122 | task.computeLoc() 123 | 124 | then: 125 | 16 == task.totalFiles 126 | 151 == task.totalLOC 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/Bar.groovy: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | /** 4 | * This is a class level Javadoc 5 | */ 6 | class Bar { 7 | /** 8 | * Method level Javadoc 9 | * @param args 10 | */ 11 | static void main(String[] args) { 12 | // Let's print out something 13 | println 'Foo' 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/Foo.java: -------------------------------------------------------------------------------- 1 | package basic; 2 | 3 | /** 4 | * This is a class level Javadoc 5 | */ 6 | public class Foo { 7 | /** 8 | * Method level Javadoc 9 | * @param args 10 | */ 11 | public static void main(String[] args) { 12 | // Let's print out something 13 | System.out.println("Foo"); 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.clj: -------------------------------------------------------------------------------- 1 | ; 2 | ; HEADER 3 | ; 4 | (setq base-version-list ; there was a base 5 | (assoc (substring fn 0 start-vn) ; version to which 6 | file-version-assoc-list)) ; this looks like 7 | ; a subversion -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.css: -------------------------------------------------------------------------------- 1 | /* 2 | HEADER 3 | */ 4 | .label { 5 | color: red; /* this is important */ 6 | } -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.fxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 11 | -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 11 | 12 | -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.js: -------------------------------------------------------------------------------- 1 | /* 2 | HEADER 3 | */ 4 | function foo() { 5 | // wow, such syntax 6 | return "JS"; /* much code */ 7 | } -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.properties: -------------------------------------------------------------------------------- 1 | # 2 | # HEADER 3 | # 4 | prop1=value 5 | # comment 6 | prop2=value -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.scss: -------------------------------------------------------------------------------- 1 | /* 2 | HEADER 3 | */ 4 | .label { 5 | // let's define a color 6 | color: red; /* this is important */ 7 | } -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.sql: -------------------------------------------------------------------------------- 1 | /* 2 | HEADER 3 | */ 4 | SELECT * FROM some_table; -- let's grab a bunch of data 5 | -- nothing more to do here -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 |
8 | 11 | -------------------------------------------------------------------------------- /src/test/projects/basic_all/src/main/java/basic/foo.yaml: -------------------------------------------------------------------------------- 1 | # HEADER 2 | key: # comment 3 | - value line 1 4 | # comment 5 | - value line 2 6 | # comment 7 | - value line 3 -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/conf/Config.groovy: -------------------------------------------------------------------------------- 1 | application { 2 | title = 'sample' 3 | startupGroups = ['sample'] 4 | autoShutdown = true 5 | } 6 | mvcGroups { 7 | // MVC Group for "sample" 8 | 'sample' { 9 | model = 'org.example.SampleModel' 10 | view = 'org.example.SampleView' 11 | controller = 'org.example.SampleController' 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/controllers/org/example/SampleController.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.artifact.GriffonController 4 | import griffon.metadata.ArtifactProviderFor 5 | 6 | @ArtifactProviderFor(GriffonController) 7 | class SampleController { 8 | SampleModel model 9 | 10 | void click() { 11 | model.clickCount++ 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/i18n/messages.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/i18n/messages.properties -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/lifecycle/Initialize.groovy: -------------------------------------------------------------------------------- 1 | import griffon.core.GriffonApplication 2 | import org.codehaus.griffon.runtime.core.AbstractLifecycleHandler 3 | 4 | import javax.annotation.Nonnull 5 | import javax.inject.Inject 6 | 7 | import static griffon.util.GriffonApplicationUtils.isMacOSX 8 | import static groovy.swing.SwingBuilder.lookAndFeel 9 | 10 | class Initialize extends AbstractLifecycleHandler { 11 | @Inject 12 | Initialize(@Nonnull GriffonApplication application) { 13 | super(application) 14 | } 15 | 16 | @Override 17 | void execute() { 18 | lookAndFeel((isMacOSX ? 'system' : 'nimbus'), 'gtk', ['metal', [boldFonts: false]]) 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/models/org/example/SampleModel.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.artifact.GriffonModel 4 | import griffon.transform.Observable 5 | import griffon.metadata.ArtifactProviderFor 6 | 7 | @ArtifactProviderFor(GriffonModel) 8 | class SampleModel { 9 | @Observable int clickCount = 0 10 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/application.properties: -------------------------------------------------------------------------------- 1 | application.name=@application.name@ 2 | application.version=@application.version@ 3 | -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-128x128.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-16x16.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-24x24.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-256x256.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-32x32.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-48x48.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon-icon-64x64.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/griffon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/griffon.png -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/resources/resources.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aalmiray/stats-gradle-plugin/a3845e6da91314319e89ae74d6312dbccfd5403c/src/test/projects/basic_griffon/griffon-app/resources/resources.properties -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/griffon-app/views/org/example/SampleView.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.artifact.GriffonView 4 | import griffon.metadata.ArtifactProviderFor 5 | import javax.swing.SwingConstants 6 | 7 | @ArtifactProviderFor(GriffonView) 8 | class SampleView { 9 | FactoryBuilderSupport builder 10 | SampleModel model 11 | 12 | void initUI() { 13 | builder.with { 14 | application(size: [320, 160], id: 'mainWindow', 15 | title: application.configuration['application.title'], 16 | iconImage: imageIcon('/griffon-icon-48x48.png').image, 17 | iconImages: [imageIcon('/griffon-icon-48x48.png').image, 18 | imageIcon('/griffon-icon-32x32.png').image, 19 | imageIcon('/griffon-icon-16x16.png').image]) { 20 | gridLayout(rows: 2, cols: 1) 21 | label(id: 'clickLabel', text: bind { model.clickCount }, 22 | horizontalAlignment: SwingConstants.CENTER) 23 | button(id: 'clickButton', clickAction) 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/integration-test/groovy/org/example/SampleIntegrationTest.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.test.GriffonFestRule 4 | import org.fest.swing.fixture.FrameFixture 5 | import org.junit.Rule 6 | import org.junit.Test 7 | 8 | class SampleIntegrationTest { 9 | static { 10 | System.setProperty('org.slf4j.simpleLogger.defaultLogLevel', 'trace') 11 | System.setProperty('griffon.swing.edt.violations.check', 'true') 12 | System.setProperty('griffon.swing.edt.hang.monitor', 'true') 13 | } 14 | 15 | @Rule 16 | public final GriffonFestRule fest = new GriffonFestRule() 17 | 18 | private FrameFixture window 19 | 20 | @Test 21 | void clickButton() { 22 | // given: 23 | window.label('clickLabel').requireText('0') 24 | 25 | // when: 26 | window.button('clickButton').click() 27 | 28 | // then: 29 | window.label('clickLabel').requireText('1') 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/main/groovy/org/example/ApplicationEventHandler.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.GriffonApplication 4 | import griffon.core.event.EventHandler 5 | 6 | class ApplicationEventHandler implements EventHandler { 7 | /* 8 | void onBootstrapStart(GriffonApplication application) { 9 | 10 | } 11 | */ 12 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/main/groovy/org/example/ApplicationModule.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.event.EventHandler 4 | import griffon.core.injection.Module 5 | import org.codehaus.griffon.runtime.core.injection.AbstractModule 6 | import org.kordamp.jipsy.ServiceProviderFor 7 | 8 | @ServiceProviderFor(Module) 9 | class ApplicationModule extends AbstractModule { 10 | @Override 11 | protected void doConfigure() { 12 | bind(EventHandler) 13 | .to(ApplicationEventHandler) 14 | .asSingleton() 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/main/groovy/org/example/Foo.java: -------------------------------------------------------------------------------- 1 | package org.example; 2 | 3 | public class Foo {} 4 | -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/main/groovy/org/example/Launcher.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.swing.SwingGriffonApplication 4 | 5 | class Launcher { 6 | static void main(String[] args) throws Exception { 7 | SwingGriffonApplication.run(SwingGriffonApplication, args) 8 | } 9 | } -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/main/java/org/example/Bar.java: -------------------------------------------------------------------------------- 1 | package org.example; 2 | 3 | public class Bar {} 4 | -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 2 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 3 | log4j.appender.stdout.layout.ConversionPattern=[%d] [%t] %-5p %-c - %m%n 4 | log4j.rootLogger=error, stdout 5 | 6 | # The default "info" level for all Griffon's public API 7 | log4j.logger.griffon=info,stdout 8 | log4j.additivity.griffon=false 9 | 10 | # This logger covers all of Griffon's internal API 11 | # Enable to see whats going on underneath. 12 | log4j.logger.org.codehaus.griffon=error,stdout 13 | log4j.additivity.org.codehaus.griffon=false 14 | log4j.logger.org.codehaus.griffon.runtime.core.AbstractApplicationBootstrapper=info,stdout 15 | log4j.additivity.org.codehaus.griffon.runtime.core.AbstractApplicationBootstrapper=false 16 | log4j.logger.org.codehaus.griffon.runtime.core.DefaultApplicationBootstrapper=info,stdout 17 | log4j.additivity.org.codehaus.griffon.runtime.core.DefaultApplicationBootstrapper=false 18 | -------------------------------------------------------------------------------- /src/test/projects/basic_griffon/src/test/groovy/org/example/SampleControllerTest.groovy: -------------------------------------------------------------------------------- 1 | package org.example 2 | 3 | import griffon.core.test.GriffonUnitRule 4 | import griffon.core.test.TestFor 5 | import org.junit.Rule 6 | import org.junit.Test 7 | 8 | import static org.junit.Assert.fail 9 | 10 | @TestFor(SampleController) 11 | class SampleControllerTest { 12 | private SampleController controller 13 | 14 | @Rule 15 | public final GriffonUnitRule griffon = new GriffonUnitRule() 16 | 17 | @Test 18 | void testClickAction() { 19 | fail('Not yet implemented!') 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/projects/basic_java/src/main/java/basic/Bar.java: -------------------------------------------------------------------------------- 1 | package basic; 2 | 3 | public class Bar { 4 | public static void main(String[] args) { 5 | // Let's print out something 6 | System.out.println("Bar"); 7 | /* do it again! */ 8 | System.out.println("Bar"); 9 | /* 10 | * And now for an meaningless 11 | * multi-line comment 12 | */ 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/projects/basic_java/src/main/java/basic/Foo.java: -------------------------------------------------------------------------------- 1 | package basic; 2 | 3 | /** 4 | * This is a class level Javadoc 5 | */ 6 | public class Foo { 7 | /** 8 | * Method level Javadoc 9 | * @param args 10 | */ 11 | public static void main(String[] args) { 12 | // Let's print out something 13 | System.out.println("Foo"); 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/projects/basic_scala/src/main/java/basic/Bar.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | object Bar { 4 | def main(args: Array[String]): Unit = { 5 | // Let's print out something 6 | println("Bar") 7 | /* do it again! */ 8 | println("Bar") 9 | /* 10 | * And now for an meaningless 11 | * multi-line comment 12 | */ 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/projects/basic_scala/src/main/java/basic/Foo.scala: -------------------------------------------------------------------------------- 1 | package basic 2 | 3 | /** 4 | * This is a class level Javadoc 5 | */ 6 | object Foo { 7 | /** 8 | * Method level Javadoc 9 | * @param args 10 | */ 11 | def main(args: Array[String]): Unit = { 12 | // Let's print out something 13 | println("Foo") 14 | } 15 | } --------------------------------------------------------------------------------