diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocMissingDocumentationInspection.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocMissingDocumentationInspection.kt new file mode 100644 index 00000000000..f22d153c074 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/kdoc/KDocMissingDocumentationInspection.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.kdoc + +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiElementVisitor +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.MemberDescriptor +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection +import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.resolve.source.getPsi + +class KDocMissingDocumentationInspection(): AbstractKotlinInspection() { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor = + KDocMissingDocumentationInspection(holder) + + private class KDocMissingDocumentationInspection(private val holder: ProblemsHolder): PsiElementVisitor() { + override fun visitElement(element: PsiElement) { + + if (element is KtNamedDeclaration) { + val nameIdentifier = element.nameIdentifier + val descriptor = element.resolveToDescriptor() as? MemberDescriptor; + if (nameIdentifier != null && descriptor?.visibility == Visibilities.PUBLIC) { + val hasDocumentation = element.docComment != null || + (descriptor as? CallableMemberDescriptor)?.overriddenDescriptors + ?.any { (it.source.getPsi() as? KtNamedDeclaration)?.docComment != null } ?: false + if (!hasDocumentation) { + holder.registerProblem(nameIdentifier, "Missing documentation") + } + } + } + } + } +} diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 9d1406ee8b8..a21ddf4ee55 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -1332,6 +1332,13 @@ level="WARNING" /> + + publicUndocumentedFun() {} +fun defaultUndocumentedFun() {} + +/** Some documentation */ +public fun publicDocumentedFun() {} + +/** Some documentation */ +fun defaultDocumentedFun() {} + +private fun privateUndocumentedFun() {} +internal fun internalUndocumentedFun() {} + + + +public class publicUndocumentedClass() {} +class defaultUndocumentedClass() {} + +/** Some documentation */ +public class publicDocumentedClass() {} + +/** Some documentation */ +class defaultDocumentedClass() {} + +private class privateUndocumentedClass() {} +internal class internalUndocumentedClass() {} + + + +private open class Properties { + + public open val publicUndocumentedProperty: Int = 0 + open val defaultUndocumentedProperty: Int = 0 + + /** Some documentation */ + public open val publicDocumentedProperty: Int = 0 + + /** Some documentation */ + open val defaultDocumentedProperty: Int = 0 + + private val privateUndocumentedProperty: Int = 0 + internal open val internalUndocumentedProperty: Int = 0 + + + protected open val protectedUndocumentedProperty: Int = 0 + protected class protectedUndocumentedClass {} + protected fun protectedUndocumentedFun() {} + + /** Some documentation */ + protected open val protectedDocumentedProperty: Int = 0 +} + +private open class ChildClass : Properties() { + override val publicUndocumentedProperty: Int = 4 + override val defaultUndocumentedProperty: Int = 4 + override val publicDocumentedProperty: Int = 4 + override val defaultDocumentedProperty: Int = 4 + + /** Some documentation */ + override public val internalUndocumentedProperty: Int = 4 + override public val protectedUndocumentedProperty: Int = 4 + override public val protectedDocumentedProperty: Int = 4 +} + +private class GrandChildClass : ChildClass() { + override public val internalUndocumentedProperty: Int = 6 +} + +// NO_CHECK_INFOS diff --git a/idea/tests/org/jetbrains/kotlin/idea/kdoc/AbstractKDocHighlightingTest.java b/idea/tests/org/jetbrains/kotlin/idea/kdoc/AbstractKDocHighlightingTest.java index cf8a75360db..63149412ef2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/kdoc/AbstractKDocHighlightingTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/kdoc/AbstractKDocHighlightingTest.java @@ -23,5 +23,6 @@ public abstract class AbstractKDocHighlightingTest extends AbstractHighlightingT protected void setUp() { super.setUp(); myFixture.enableInspections(KDocUnresolvedReferenceInspection.class); + myFixture.enableInspections(KDocMissingDocumentationInspection.class); } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocHighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocHighlightingTestGenerated.java index 64f51100f95..2ee7eb7e8e9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocHighlightingTestGenerated.java @@ -35,6 +35,12 @@ public class KDocHighlightingTestGenerated extends AbstractKDocHighlightingTest KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/kdoc/highlighting"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("MissingDocumentation.kt") + public void testMissingDocumentation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/highlighting/MissingDocumentation.kt"); + doTest(fileName); + } + @TestMetadata("UnresolvedReference.kt") public void testUnresolvedReference() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kdoc/highlighting/UnresolvedReference.kt");