Repository: analysis-dev/diktat (kotlin)

Issue:
Copyright text for copyright rule should be able to contain patters for current year

Pull request:
### What's done:
* Improvements for Copyrights rule - support pattern for the current year in the configuration

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt
index 82e4db265f..42699002b2 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter2/comments/HeaderCommentRule.kt
@@ -135,13 +135,13 @@ class HeaderCommentRule(configRules: List<RulesConfig>) : DiktatRule(
             return
         }
 
-        if (makeCopyrightCorrectYear(configuration.getCopyrightText()).isNotEmpty()) {
-            log.warn("Copyright year is not up do date.")
-        }
-
         // need to make sure that copyright year is consistent with current year
         val copyrightText = configuration.getCopyrightText()
 
+        if (makeCopyrightCorrectYear(copyrightText).isNotEmpty()) {
+            log.warn("Copyright year is not up do date.")
+        }
+
         val headerComment = node.findChildBefore(PACKAGE_DIRECTIVE, BLOCK_COMMENT)
         // Depends only on content and doesn't consider years
         val isWrongCopyright = headerComment != null &&
@@ -234,11 +234,13 @@ class HeaderCommentRule(configRules: List<RulesConfig>) : DiktatRule(
         /**
          * @return text of copyright as configured in the configuration file
          */
-        fun getCopyrightText() = config["copyrightText"] ?: error("Copyright is not set in configuration")
+        fun getCopyrightText() = config["copyrightText"]?.replace(CURR_YEAR_PATTERN, curYear.toString())
+            ?: error("Copyright is not set in configuration")
     }
 
     companion object {
         private val log = LoggerFactory.getLogger(HeaderCommentRule::class.java)
+        const val CURR_YEAR_PATTERN = ";@currYear;"
         val hyphenRegex = Regex("""\d+-\d+""")
         val afterCopyrightRegex = Regex("""((©|\([cC]\))+ *\d+)""")
         val curYear = LocalDate.now().year
diff --git a/info/available-rules.md b/info/available-rules.md
index 915eaa47f1..31abb5625c 100644
--- a/info/available-rules.md
+++ b/info/available-rules.md
@@ -44,7 +44,7 @@
 |    2  |     2.2.1  |  KDOC_CONTAINS_DATE_OR_AUTHOR             |  Check: warns if header KDoc contains `@author` tag.<br>Warns if `@since` tag contains version and not date.                                                                                                                                    |   no  |  no  | Detect author by other patterns (e.g. 'created by' etc.)|
 |    2  |     2.3.1  |  KDOC_TRIVIAL_KDOC_ON_FUNCTION            |  Check: warns if KDoc contains single line with words 'return', 'get' or 'set'                                                                                                 |   no  |  no  | |
 |    2  |     2.2.1  |  HEADER_WRONG_FORMAT                      |  Checks: warns if there is no newline after header KDoc<br>Fix: adds newline                                                                                                   |  yes  |  no  | Check if header is on the very top of file. It's hard to determine when it's not.|
-|    2  |     2.2.1  |  HEADER_MISSING_OR_WRONG_COPYRIGHT        |  Checks: copyright exists on top of file and is properly formatted (as a block comment)<br>Fix: adds copyright if it is missing and required                                   |  yes  | mandatoryCopyright | Allow setting copyright patterns via configuration|
+|    2  |     2.2.1  |  HEADER_MISSING_OR_WRONG_COPYRIGHT        |  Checks: copyright exists on top of file and is properly formatted (as a block comment)<br>Fix: adds copyright if it is missing and required                                   |  yes  | isCopyrightMandatory, copyrightText (sets the copyright pattern for your project, you also can use `;@currYear;` key word in your text in aim to indicate current year, instead of explicit specifying) | |
 |    2  |     2.2.1  |  WRONG_COPYRIGHT_YEAR                     |  Checks: copyright have a valid year<br>Fix: makes a year valid                                                                                                                |  yes  |  no  |  - |
 |    2  |     2.2.1  |  HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE  |  Check: warns if file with zero or >1 classes doesn't have header KDoc                                                                                                         |   no  |  no  | |
 |    2  |     2.4.2  |  COMMENTED_OUT_CODE                       |  Check: warns if commented code is detected (when un-commented, can be parsed)                                                                                                 |   no  |  no  | Offset is lost when joined EOL comments are split again|


Test patch:
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt
index 590183d679..e02c7a386b 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleFixTest.kt
@@ -37,6 +37,18 @@ class HeaderCommentRuleFixTest : FixTestBase(
         fixAndCompare("AutoCopyrightExpected.kt", "AutoCopyrightTest.kt")
     }
 
+    @Test
+    @Tag(WarningNames.HEADER_MISSING_OR_WRONG_COPYRIGHT)
+    fun `if no copyright is present, added it and apply pattern for current year`() {
+        fixAndCompare("AutoCopyrightApplyPatternExpected.kt", "AutoCopyrightApplyPatternTest.kt",
+            listOf(RulesConfig(HEADER_MISSING_OR_WRONG_COPYRIGHT.name, true,
+                mapOf(
+                    "isCopyrightMandatory" to "true",
+                    "copyrightText" to "Copyright (c) Huawei Technologies Co., Ltd. 2020-;@currYear;. All rights reserved.")
+            ),
+                RulesConfig(HEADER_WRONG_FORMAT.name, true, emptyMap())))
+    }
+
     /**
      * Fixme there shouldn't be an additional blank line after copyright
      */
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt
index fb91c8ea2c..6f35d6fa1c 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter2/HeaderCommentRuleTest.kt
@@ -24,6 +24,10 @@ class HeaderCommentRuleTest : LintTestBase(::HeaderCommentRule) {
         RulesConfig("HEADER_MISSING_OR_WRONG_COPYRIGHT", true,
             mapOf("copyrightText" to "Copyright (c) My Company, Ltd. 2012-$curYear. All rights reserved."))
     )
+    private val rulesConfigListWithPattern: List<RulesConfig> = listOf(
+        RulesConfig("HEADER_MISSING_OR_WRONG_COPYRIGHT", true,
+            mapOf("copyrightText" to "Copyright (c) My Company, Ltd. 2012-;@currYear;. All rights reserved."))
+    )
     private val rulesConfigListInvalidYear: List<RulesConfig> = listOf(
         RulesConfig("HEADER_MISSING_OR_WRONG_COPYRIGHT", true,
             mapOf("copyrightText" to "Copyright (c) My Company, Ltd. 2012-2019. All rights reserved."))
@@ -36,6 +40,10 @@ class HeaderCommentRuleTest : LintTestBase(::HeaderCommentRule) {
         RulesConfig("HEADER_MISSING_OR_WRONG_COPYRIGHT", true,
             mapOf("copyrightText" to "Copyright (c) $curYear My Company, Ltd. All rights reserved."))
     )
+    private val rulesConfigListYearWithPattern: List<RulesConfig> = listOf(
+        RulesConfig("HEADER_MISSING_OR_WRONG_COPYRIGHT", true,
+            mapOf("copyrightText" to "Copyright (c) ;@currYear; My Company, Ltd. All rights reserved."))
+    )
     private val rulesConfigListCn: List<RulesConfig> = listOf(
         RulesConfig("HEADER_MISSING_OR_WRONG_COPYRIGHT", true,
             mapOf("copyrightText" to "版权所有 (c) 华为技术有限公司 2012-$curYear"))
@@ -207,6 +215,52 @@ class HeaderCommentRuleTest : LintTestBase(::HeaderCommentRule) {
         )
     }
 
+    @Test
+    @Tag(WarningNames.WRONG_COPYRIGHT_YEAR)
+    fun `copyright year good 3 - apply pattern`() {
+        lintMethod(
+            """
+                /*
+                 * Copyright (c) 2021 My Company, Ltd. All rights reserved.
+                 */
+                /**
+                 * Very useful description, why this file has two classes
+                 * foo bar baz
+                 */
+
+                package org.cqfn.diktat.example
+
+                class Example1 { }
+
+                class Example2 { }
+            """.trimIndent(),
+            rulesConfigList = rulesConfigListYearWithPattern
+        )
+    }
+
+    @Test
+    @Tag(WarningNames.WRONG_COPYRIGHT_YEAR)
+    fun `copyright year good 4 - apply pattern`() {
+        lintMethod(
+            """
+                /*
+                 * Copyright (c) My Company, Ltd. 2012-2021. All rights reserved.
+                 */
+                /**
+                 * Very useful description, why this file has two classes
+                 * foo bar baz
+                 */
+
+                package org.cqfn.diktat.example
+
+                class Example1 { }
+
+                class Example2 { }
+            """.trimIndent(),
+            rulesConfigList = rulesConfigListWithPattern
+        )
+    }
+
     @Test
     @Tag(WarningNames.WRONG_COPYRIGHT_YEAR)
     fun `copyright year bad`() {
diff --git a/diktat-rules/src/test/resources/test/paragraph2/header/AutoCopyrightApplyPatternExpected.kt b/diktat-rules/src/test/resources/test/paragraph2/header/AutoCopyrightApplyPatternExpected.kt
new file mode 100644
index 0000000000..65ed8fbd98
--- /dev/null
+++ b/diktat-rules/src/test/resources/test/paragraph2/header/AutoCopyrightApplyPatternExpected.kt
@@ -0,0 +1,7 @@
+/*
+    Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.
+*/
+
+package test.paragraph2.header
+
+class Example
diff --git a/diktat-rules/src/test/resources/test/paragraph2/header/AutoCopyrightApplyPatternTest.kt b/diktat-rules/src/test/resources/test/paragraph2/header/AutoCopyrightApplyPatternTest.kt
new file mode 100644
index 0000000000..993117dd44
--- /dev/null
+++ b/diktat-rules/src/test/resources/test/paragraph2/header/AutoCopyrightApplyPatternTest.kt
@@ -0,0 +1,3 @@
+package test.paragraph2.header
+
+class Example
\ No newline at end of file