diff --git a/scripts/ktlint_lint_check.sh b/scripts/ktlint_lint_check.sh index dab25e7bd64..2e5068d773e 100755 --- a/scripts/ktlint_lint_check.sh +++ b/scripts/ktlint_lint_check.sh @@ -16,7 +16,7 @@ else jar_file_path="$github_actions_path/oppia-android-tools/ktlint" fi -java -jar $jar_file_path --android app/src/**/*.kt data/src/**/*.kt domain/src/**/*.kt testing/src/**/*.kt utility/src/**/*.kt scripts/src/**/*.kt instrumentation/src/**/*.kt +java -jar $jar_file_path -R ../oppia-android-tools/custom-ktlint-rules.jar --android app/src/**/*.kt data/src/**/*.kt domain/src/**/*.kt testing/src/**/*.kt utility/src/**/*.kt scripts/src/**/*.kt instrumentation/src/**/*.kt status=$? @@ -27,10 +27,10 @@ else echo "********************************" echo_error "Ktlint issue found." echo "Please fix the above issues. - You can also use the java -jar $jar_file_path -F --android domain/src/**/*.kt utility/src/**/*.kt data/src/**/*.kt app/src/**/*.kt testing/src/**/*.kt scripts/src/**/*.kt instrumentation/src/**/*.kt + You can also use the java -jar $jar_file_path -F -R ../oppia-android-tools/custom-ktlint-rules.jar --android domain/src/**/*.kt utility/src/**/*.kt data/src/**/*.kt app/src/**/*.kt testing/src/**/*.kt scripts/src/**/*.kt instrumentation/src/**/*.kt command to fix the most common issues." echo_warning "Please note, there might be a possibility where the above command will not fix the issue. In that case, you will have to fix it yourself." echo "********************************" exit 1 -fi +fi \ No newline at end of file diff --git a/utility/build.gradle b/utility/build.gradle index 53e7905913f..73de9693374 100644 --- a/utility/build.gradle +++ b/utility/build.gradle @@ -17,7 +17,6 @@ android { } } } - compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -98,6 +97,7 @@ dependencies { 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2', 'javax.annotation:javax.annotation-api:1.3.2', 'org.glassfish.jaxb:jaxb-runtime:2.3.2', + 'com.pinterest.ktlint:ktlint-core:0.37.1', ) testImplementation( 'androidx.test.ext:junit:1.1.1', @@ -125,6 +125,25 @@ dependencies { // controlled more directly than in Gradle. implementation project(':model') } +// Custom task to create a JAR file for ktlint rules. +tasks.register('customRulesJar', Jar) { + archiveFileName = 'custom-ktlint-rules.jar' + from("$buildDir/tmp/kotlin-classes/debug") { + include '**/*.class' + } + from('src/main/res') { + include 'META-INF/services/**' + } + manifest { + attributes( + 'Implementation-Title': 'Oppia Android Custom KtLint Rules', + 'Implementation-Version': '1.0.0' + ) + } + // Ensure that Kotlin and Java classes are compiled before creating the JAR. + dependsOn 'compileDebugKotlin', 'compileDebugJavaWithJavac' + destinationDirectory.set(file("../../oppia-android-tools")) +} // The GeneratedMessageLite implementations of protobufs are depending on protobuf-java // instead of protobuf-lite after Android Studio 3.5, // The below command stops that from happening: https://github.com/google/tink/issues/282 diff --git a/utility/src/main/java/org/oppia/android/util/ktlint/CustomRuleSetProvider.kt b/utility/src/main/java/org/oppia/android/util/ktlint/CustomRuleSetProvider.kt new file mode 100644 index 00000000000..517054d24db --- /dev/null +++ b/utility/src/main/java/org/oppia/android/util/ktlint/CustomRuleSetProvider.kt @@ -0,0 +1,10 @@ +package org.oppia.android.util.ktlint + +import com.pinterest.ktlint.core.RuleSet +import com.pinterest.ktlint.core.RuleSetProvider +import org.oppia.android.util.ktlint.rules.KDocFormatRule + +class CustomRuleSetProvider : RuleSetProvider { + + override fun get(): RuleSet = RuleSet("custom", KDocFormatRule()) +} diff --git a/utility/src/main/java/org/oppia/android/util/ktlint/rules/KDocFormatRule.kt b/utility/src/main/java/org/oppia/android/util/ktlint/rules/KDocFormatRule.kt new file mode 100644 index 00000000000..002f92d7eda --- /dev/null +++ b/utility/src/main/java/org/oppia/android/util/ktlint/rules/KDocFormatRule.kt @@ -0,0 +1,36 @@ +package org.oppia.android.util.ktlint.rules + +import com.pinterest.ktlint.core.Rule +import org.jetbrains.kotlin.com.intellij.lang.ASTNode +import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement +import org.jetbrains.kotlin.kdoc.psi.impl.KDocImpl +import org.jetbrains.kotlin.psi.KtFile + +class KDocFormatRule : Rule("kdoc-format-closing") { + override fun visit( + node: ASTNode, + autoCorrect: Boolean, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit, + ) { + if (node.psi is KtFile) { + val kdocs = node.psi.children.filterIsInstance() + kdocs.forEach { kdoc -> + val lines = kdoc.text.lines() + if (lines.last().contains("* */")) { + emit( + kdoc.startOffset + kdoc.text.lastIndexOf("* *"), + "KDoc closing should be ' */' not '* */'", + true, + ) + if (autoCorrect) { + val kdocNode = kdoc.node + val oldText = kdocNode.text + val newText = oldText.replace("* */", " */") + val correctedNode = LeafPsiElement(kdocNode.elementType, newText) + kdocNode.treeParent.replaceChild(kdocNode, correctedNode) + } + } + } + } + } +} diff --git a/utility/src/main/res/META-INF/services/com.pinterest.ktlint.core.RuleSetProvider b/utility/src/main/res/META-INF/services/com.pinterest.ktlint.core.RuleSetProvider new file mode 100644 index 00000000000..b562f329cec --- /dev/null +++ b/utility/src/main/res/META-INF/services/com.pinterest.ktlint.core.RuleSetProvider @@ -0,0 +1 @@ +org.oppia.android.util.ktlint.CustomRuleSetProvider