{"id":15830137,"url":"https://github.com/aaschmid/gradle-cpd-plugin","last_synced_at":"2025-08-20T08:33:26.612Z","repository":{"id":15989935,"uuid":"18733100","full_name":"aaschmid/gradle-cpd-plugin","owner":"aaschmid","description":"Gradle plugin to find duplicate code using PMDs copy/paste detection (= CPD).","archived":false,"fork":false,"pushed_at":"2024-06-03T20:38:46.000Z","size":670,"stargazers_count":95,"open_issues_count":5,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-12T11:14:10.229Z","etag":null,"topics":["copy","cpd","detection","gradle-cpd-plugin","gradle-plugin","paste"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aaschmid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.TXT","code_of_conduct":"CODE-OF-CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-04-13T15:57:43.000Z","updated_at":"2024-08-05T10:39:01.000Z","dependencies_parsed_at":"2024-10-26T16:07:37.741Z","dependency_job_id":"0fefdd63-9e1d-40ba-b204-eb047c792799","html_url":"https://github.com/aaschmid/gradle-cpd-plugin","commit_stats":{"total_commits":266,"total_committers":8,"mean_commits":33.25,"dds":0.09398496240601506,"last_synced_commit":"136f9b0628cd772af59023afa96f7a7f092d24d6"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaschmid%2Fgradle-cpd-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaschmid%2Fgradle-cpd-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaschmid%2Fgradle-cpd-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaschmid%2Fgradle-cpd-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aaschmid","download_url":"https://codeload.github.com/aaschmid/gradle-cpd-plugin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230408171,"owners_count":18220974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["copy","cpd","detection","gradle-cpd-plugin","gradle-plugin","paste"],"created_at":"2024-10-05T11:04:57.811Z","updated_at":"2024-12-19T09:08:04.153Z","avatar_url":"https://github.com/aaschmid.png","language":"Java","funding_links":[],"categories":["others"],"sub_categories":[],"readme":"[![TravisCI](https://travis-ci.org/aaschmid/gradle-cpd-plugin.svg?branch=master)](https://travis-ci.org/aaschmid/gradle-cpd-plugin)\n[![CircleCI](https://circleci.com/gh/aaschmid/gradle-cpd-plugin.svg?style=svg)](https://circleci.com/gh/aaschmid/gradle-cpd-plugin)\n[![Coverage Status](https://coveralls.io/repos/github/aaschmid/gradle-cpd-plugin/badge.svg?branch=master)](https://coveralls.io/github/aaschmid/gradle-cpd-plugin?branch=master)\n[![codecov](https://codecov.io/gh/aaschmid/gradle-cpd-plugin/branch/master/graph/badge.svg)](https://codecov.io/gh/aaschmid/gradle-cpd-plugin)\n[![codebeat badge](https://codebeat.co/badges/ea643af5-89e9-4b6c-8d46-11199fcac3b5)](https://codebeat.co/projects/github-com-aaschmid-gradle-cpd-plugin)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/de.aaschmid/gradle-cpd-plugin/badge.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22de.aaschmid%22%20AND%20a%3A%22gradle-cpd-plugin%22)\n[![Bintray](https://api.bintray.com/packages/aaschmid/gradle-plugins/gradle-cpd-plugin/images/download.svg)](https://bintray.com/aaschmid/gradle-plugins/gradle-cpd-plugin/_latestVersion)\n[![license](https://img.shields.io/github/license/aaschmid/gradle-cpd-plugin.svg)](https://github.com/aaschmid/gradle-cpd-plugin)\n[![Issues](https://img.shields.io/github/issues/aaschmid/gradle-cpd-plugin.svg)](https://github.com/aaschmid/gradle-cpd-plugin/issues)\n[![Forks](https://img.shields.io/github/forks/aaschmid/gradle-cpd-plugin.svg)](https://github.com/aaschmid/gradle-cpd-plugin/network)\n[![Stars](https://img.shields.io/github/stars/aaschmid/gradle-cpd-plugin.svg)](https://github.com/aaschmid/gradle-cpd-plugin/stargazers)\n\n\nGradle CPD plugin\n=================\n\n##### Table of Contents\n* [What is it](#what-is-it)\n* [Requirements](#requirements)\n* [Usage](#usage)\n* [Options](#options)\n* [Contributing](#contributing)\n* [Release notes](/../../releases)\n\n\nWhat is it\n----------\n\nA [Gradle](http://gradle.org) plugin to find duplicate code using [PMD][]s copy/paste detection (= [CPD][]). See also\nhttps://plugins.gradle.org/plugin/de.aaschmid.cpd.\n\n\nRequirements\n------------\n\nThis plugin requires [PMD](https://pmd.github.io/) greater or equal to version 7.4.0 such that ```toolVersion \u003e= '7.4.0'```.\n\nYou can use older versions of this plugin if you want to use older versions of PMD (see table below).\n\n### Supported versions\n\n| G. CPD plugin | Gradle       | PMD          | Java¹  |\n|:--------------|:------------ |:-------------|:------ |\n| [v0.1][]      | 1.10 - 4.x   | 5.0.0 - 5.x  | 6 - 8  |\n| [v0.2][]      | 2.0 - 4.x    | 5.0.0 - 5.x  | 6 - 8  |\n| [v0.4][]      | 2.3 - 4.x    | 5.2.0 - 5.x  | 6 - 8  |\n| [v1.0][]      | 2.14 - 5.0   | 5.2.0 - 5.x  | 6 - 8  |\n| [v1.1][]      | 2.14 - 5.0   | 5.2.2 - 6.x  | 6 - 9  |\n| [v1.2][]      | \u003e= 3.5.1     | 5.2.2 - 6.x  | \u003e= 8   |\n| [v1.3][]      | \u003e= 4.10.3    | 5.2.2 - 6.x  | \u003e= 8   |\n| [v2.0][]      | 4.10.3 - 5.5 | 6.1.0 - 6.x  | \u003e= 8   |\n| [v3.0][]      | 5.6 - 5.x    | 6.10.0 - 6.x | \u003e= 8   |\n| [v3.1][]      | \u003e= 5.6       | 6.10.0 - 6.x | \u003e= 8   |\n| [v3.2][]      | \u003e= 6.6       | 6.10.0 - 6.x | \u003e= 8   |\n| [v3.3][]      | \u003e= 6.6       | 6.10.0 - 6.x | \u003e= 8   |\n| [v3.4][]      | \u003e= 7.4       | \u003e= 7.0.0     | \u003e= 8   |\n| [v3.5][]      | \u003e= 7.4       | \u003e= 7.4.0     | \u003e= 8   |\n\n¹: Java version may additionally depend on [PMD][]s version which is might not be properly reflected here.\n\nUsage\n-----\n\nThis plugin is available using either the new [Gradle plugins DSL](https://gradle.org/docs/current/userguide/plugins.html#sec:plugins_block)\n\n\n```groovy\nplugins {\n    id 'de.aaschmid.cpd' version '3.4'\n}\n```\n\nor the old fashion [buildscript block](https://gradle.org/docs/current/userguide/plugins.html#sec:applying_plugins_buildscript)\nfrom [Maven Central](http://search.maven.org/#search|ga|1|gradle-cpd-plugin) or\n[jCenter](https://bintray.com/aaschmid/gradle-plugins/gradle-cpd-plugin/view).\n```groovy\nbuildscript {\n    repositories {\n        // choose your preferred one\n        mavenCentral()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'de.aaschmid:gradle-cpd-plugin:3.4'\n    }\n}\napply plugin: 'de.aaschmid.cpd'\n```\n\n**Attention:** The plugin's groupId was changed from ```de.aaschmid.gradle.plugins``` to ```de.aaschmid``` in [v1.0][].\n\nBy default, the copy-paste-detection looks at all source code of all projects which at least apply ```LifecycleBasePlugin```.\nIf you use a different programming language and want to get it configured out of the box, please open an issue :-)\n\n### Single module project\n\nIf you have a single module project you just need to make sure that the ```LifecycleBasePlugin``` is also applied to it\n(explicitly or implicitly through e.g. Java or Groovy plugin). Otherwise, you can simply add a dependency to a task you like by\n\n```groovy\nanalyze.dependsOn(cpdCheck)\n```\n\n### Multi module project\n\nIf the root project of your multi-module project applies the ```LifecycleBasePlugin```, you are done. But most likely this\nis not how your project looks like. If so, you need to manually add a task graph dependency manually to either one or all\nof your subprojects such that the ```cpdCheck``` task is executed:\n\n```groovy\n// one single subproject where 'LifecycleBasePlugin' is available\nsubprojectOne.check.dependsOn(':cpdCheck')\n\n// all subprojects where 'check' task is available (which comes with 'LifecycleBasePlugin')\nsubprojects {\n    plugins.withType(LifecycleBasePlugin) { // \u003c- just if 'LifecycleBasePlugin' plugin is not applied to all subprojects\n        check.dependsOn(rootProject.cpdCheck)\n    }\n}\n```\n\n### Custom sourceSets\n\nIf you are adding custom sourceSets (even in subProjects), it may occur that you either need to configure `cpdCheck`\nafterwards or even manually configure `source`. Unfortunately, I have had problems with this case in the\n[CpdAcceptanceTest](https://github.com/aaschmid/gradle-cpd-plugin/blob/master/src/integTest/groovy/de/aaschmid/gradle/plugins/cpd/test/CpdAcceptanceTest.groovy)\ntests using Gradle [TestKit](https://docs.gradle.org/current/userguide/test_kit.html).\n\n\n### Examples\n\nThis example shows a project where only ```main``` sources should be checked for duplicates:\n\n```groovy\n// optional - settings for every CPD task\ncpd {\n    language = 'cpp'\n    toolVersion = '7.4.0' // defaults to '7.7.0'; just available for v7.4.0 and higher (see explanation above)\n}\n\n// optional - default report is xml and default sources are 'main' and 'test'\ncpdCheck {\n    reports {\n        text.enabled = true\n        xml.enabled = false\n    }\n    source = sourceSets.main.allJava // only java, groovy and scala classes in 'main' sourceSets\n}\n```\n\n*Note:* With v0.2, I have renamed the default task from ```cpd``` to ```cpdCheck``` so that it does not have a name clash anymore.\n\n### Property `source`\n\nDepending on your needs, java sourcesets of all projects will be automatically added to `source` and therefore checked for duplicates (see [Code](https://github.com/aaschmid/gradle-cpd-plugin/blob/%2350.text.fixture/src/main/java/de/aaschmid/gradle/plugins/cpd/CpdPlugin.java#L79-L88)). You have a lot of options for overriding this behaviour but note that the lazy evaluation - especially later configured subprojects - could add further `sourceSets` again unless you use `[evaluationDependsOnChildren()](https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#evaluationDependsOnChildren--)` for your `rootProject`:\n\n```groovy\nsource = subprojects*.sourceSets*.main*.java*.srcDirs\n```\nor\n```groovy\nsource = subprojects*.sourceSets*.main*.java*.srcDirs + subprojects*.sourceSets*.test*.java*.srcDirs\n```\nor\n```groovy\ncpdCheck {\n    source = []\n    allprojects.forEach { project -\u003e\n        project.plugins.withType(JavaPlugin) { plugin -\u003e\n            project.sourceSets.main.java.forEach { s -\u003e rootProject.cpdCheck.source(s) }\n        }\n    }\n}\n```\nor same using kotlin DSL (Note: That works only if all `subprojects` have `sourceSets` `main` and `test` e.g. by appling the `java` plugins. Otherwise, you can just filter for `JavaBasePlugin` before)\n```kotlin\nsetSource(files(\n    // only check java source code\n    subprojects.flatMap { it.the\u003cSourceSetContainer\u003e()[\"main\"].java.srcDirs },\n    subprojects.flatMap { it.the\u003cSourceSetContainer\u003e()[\"test\"].java.srcDirs }\n))\n```\nor if you need a new cpd task for kotlin and not all `subprojects` apply a `java` plugin (see also [here](https://github.com/aaschmid/gradle-cpd-plugin/issues/39#issuecomment-488730600))\n```kotlin\ntasks.register\u003cCpd\u003e(\"cpdKotlin\") {\n    language = \"kotlin\"\n    exclude { it.file.extension.contains(\"java\") }\n\n    allprojects.forEach { project -\u003e\n        project.plugins.withType\u003cJavaPlugin\u003e {\n            project.convention.getPlugin\u003cJavaPluginConvention\u003e().sourceSets.configureEach {\n                allJava.srcDirTrees.forEach { this@register.source(it) }\n            }\n        }\n    }\n}\n```\n\n### Kotlin support\n\n[CPD][] supports [Kotlin](https://kotlinlang.org/) since\n[v6.10.0](https://search.maven.org/search?q=g:net.sourceforge.pmd%20AND%20a:pmd-kotlin\u0026core=gav). For previous versions\nyou have to ignore files manually if you mixed it up with your Java files:\n```groovy\ntasks.withType(Cpd) {\n    exclude \"*.kt\"\n}\n```\n\nOptions\n-------\n\nThis plugin supports the following options, either set for the plugin using ```cpd { }``` or for every task explicitly,\ne.g. using ```cpdCheck { }```:\n\n| Attribute          | Default              | Applies for ```language``` | since    |\n| ------------------ |:--------------------:|:--------------------------:|:--------:|\n| encoding           | System default       |                            | [v0.1][] |\n| failOnError        |      ```true```      |                            | [v3.5][] |\n| failOnViolation    |      ```true```      |                            | [v3.5][] |\n| ignoreAnnotations  | ```false```          | ```'java'```               | [v0.4][] |\n| ignoreFailures     | ```false```          |                            | [v0.1][] |\n| ignoreIdentifiers  | ```false```          | ```'java'```               | [v0.4][] |\n| ignoreLiterals     | ```false```          | ```'java'```               | [v0.4][] |\n| language           | ```'java'```         |                            | [v0.4][] |\n| minimumTokenCount  | ```50```             |                            | [v0.1][] |\n| skipDuplicateFiles | ```false```          |                            | [v0.5][] |\n| skipLexicalErrors  | ```false```          |                            | [v0.5][] |\n| skipBlocks         | ```true```           | ```'cpp'```                | [v0.4][] |\n| skipBlocksPattern  | ```'#if 0\\|#endif'``` | ```'cpp'```               | [v0.4][] |\n\nIf a specified `language` cannot be found, analysis fails.\n\nFor more information about options and their descriptions, see [here](https://pmd.github.io/latest/pmd_userdocs_cpd.html#attribute-reference),\nand for the available programming languages have a look on [CPD documentation](https://pmd.github.io/latest/pmd_userdocs_cpd.html#supported-languages).\nTo request more options, please file an issue [here](/../../issues).\n\n\nAdditionally, one can configure the following reports for every task analogous to\n[Reporting](https://gradle.org/docs/current/dsl/org.gradle.api.reporting.Reporting.html) as for any other reporting plugin. See also\nthe example in [Usage](#usage) section above.\n\n| Report | Default  | since    | Further options and their defaults                        |\n| ------ |:--------:| -------- | --------------------------------------------------------- |\n| csv    | disabled | [v0.1][] | ```separator = ','```, ```includeLineCount = true```**²** |\n| text   | disabled | [v0.1][] | ```lineSeparator = '====================================================================='```, ```trimLeadingCommonSourceWhitespaces = false``` |\n| vs     | disabled | [v3.1][] | ```encoding = \u003c\u003cSystem default\u003e\u003e```                       |\n| xml    | enabled  | [v0.1][] | ```encoding = \u003c\u003cSystem default\u003e\u003e```                       |\n\n²: Since [v3.1][] but note that property `includeLineCount` is originally named `lineCountPerFile` and meaning is inverted which means that\n`false` shows line count and `true` hides it, see\n[here](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CSVRenderer.java#L63).\n\n\nContributing\n------------\n\nYou are very welcome to contribute by providing a patch/pull request.\n\nPlease note that running the test cases my take quite long because the acceptance test cases (see\n```de.aaschmid.gradle.plugins.cpd.test.CpdAcceptanceTest``` will download [CPD][] and its dependencies for every version. I recommend to\nget these dependencies in your ```localMaven()``` repository as the test cases look there for it first.\n\n[PMD]: https://pmd.github.io/\n[CPD]: https://pmd.github.io/latest/pmd_userdocs_cpd.html\n\n[v0.1]: /../../releases/tag/v0.1\n[v0.2]: /../../releases/tag/v0.2\n[v0.4]: /../../releases/tag/v0.4\n[v0.5]: /../../releases/tag/v0.5\n[v1.0]: /../../releases/tag/v1.0\n[v1.1]: /../../releases/tag/v1.1\n[v1.2]: /../../releases/tag/v1.2\n[v1.3]: /../../releases/tag/v1.3\n[v2.0]: /../../releases/tag/v2.0\n[v3.0]: /../../releases/tag/v3.0\n[v3.1]: /../../releases/tag/v3.1\n[v3.2]: /../../releases/tag/v3.2\n[v3.3]: /../../releases/tag/v3.3\n[v3.4]: /../../releases/tag/v3.4\n[v3.5]: /../../releases/tag/v3.5\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaschmid%2Fgradle-cpd-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faaschmid%2Fgradle-cpd-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaschmid%2Fgradle-cpd-plugin/lists"}