diff --git a/core/builtins/native/kotlin/Enum.kt b/core/builtins/native/kotlin/Enum.kt index 1feeed4437e..d3009e6fbf8 100644 --- a/core/builtins/native/kotlin/Enum.kt +++ b/core/builtins/native/kotlin/Enum.kt @@ -46,4 +46,16 @@ public abstract class Enum>(name: String, ordinal: Int): Comparable< public override final fun equals(other: Any?): Boolean public override final fun hashCode(): Int public override fun toString(): String + + /** + * Returns an array containing the constants of this enum type, in the order they're declared. + * This method may be used to iterate over the constants. + * @values + */ + + /** + * Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) + * @throws IllegalArgumentException if this enum type has no constant with the specified name + * @valueOf + */ } diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt index 1f5d0955262..45abdaf5c20 100644 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt @@ -27,14 +27,13 @@ import com.intellij.psi.PsiManager import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject +import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper import org.jetbrains.kotlin.idea.kdoc.KDocRenderer import org.jetbrains.kotlin.idea.kdoc.findKDoc import org.jetbrains.kotlin.idea.kdoc.isBoringBuiltinClass @@ -42,15 +41,18 @@ import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi +import org.jetbrains.kotlin.kdoc.psi.api.KDoc +import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.renderer.ClassifierNamePolicy import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.deprecatedByAnnotationReplaceWithExpression +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.resolve.getDeprecations import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.utils.addToStdlib.constant @@ -102,8 +104,60 @@ class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { renderCompanionObjectName = true } + private fun renderEnumSpecialFunction(element: KtClass, functionDescriptor: FunctionDescriptor, quickNavigation: Boolean): String { + var renderedDecl = DESCRIPTOR_RENDERER.render(functionDescriptor) + + if (quickNavigation) return renderedDecl + + val declarationDescriptor = element.resolveToDescriptorIfAny() + val enumDescriptor = (declarationDescriptor as? ClassDescriptor)?.getSuperClassNotAny() ?: return renderedDecl + + val enumDeclaration = + DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, enumDescriptor) as? KtDeclaration ?: return renderedDecl + + val enumSource = SourceNavigationHelper.getNavigationElement(enumDeclaration) + val functionName = functionDescriptor.fqNameSafe.shortName().asString() + val kdoc = enumSource.findDescendantOfType { + it.getChildrenOfType().any { it.findTagByName(functionName) != null } + } + + if (kdoc != null) { + val renderedComment = KDocRenderer.renderKDoc(kdoc.getDefaultSection()) + if (renderedComment.startsWith("

")) { + renderedDecl += renderedComment + } + else { + renderedDecl = "$renderedDecl
$renderedComment" + } + } + + return renderedDecl + } + + private fun renderEnum(element: KtClass, originalElement: PsiElement?, quickNavigation: Boolean): String? { + val referenceExpression = originalElement?.getNonStrictParentOfType() + if (referenceExpression != null) { + // When caret on special enum function (e.g SomeEnum.values()) + // element is not an KtReferenceExpression, but KtClass of enum + // so reference extracted from originalElement + val context = referenceExpression.analyze(BodyResolveMode.PARTIAL) + (context[BindingContext.REFERENCE_TARGET, referenceExpression] ?: + context[BindingContext.REFERENCE_TARGET, referenceExpression.getChildOfType()])?.let { + if (it is FunctionDescriptor) // To protect from SomeEnum.values() + return renderEnumSpecialFunction(element, it, quickNavigation) + } + } + return renderKotlinDeclaration(element, quickNavigation) + } + private fun getText(element: PsiElement, originalElement: PsiElement?, quickNavigation: Boolean): String? { - if (element is KtDeclaration) { + + if (element is KtClass && element.isEnum()) { + // When caret on special enum function (e.g SomeEnum.values()) + // element is not an KtReferenceExpression, but KtClass of enum + return renderEnum(element, originalElement, quickNavigation) + } + else if (element is KtDeclaration) { return renderKotlinDeclaration(element, quickNavigation) } else if (element is KtNameReferenceExpression && element.getReferencedName() == "it") { diff --git a/idea/testData/editor/quickDoc/OnEnumClassReference.kt b/idea/testData/editor/quickDoc/OnEnumClassReference.kt new file mode 100644 index 00000000000..25a6d9e334c --- /dev/null +++ b/idea/testData/editor/quickDoc/OnEnumClassReference.kt @@ -0,0 +1,10 @@ +/** + * Useless one + */ +enum class SomeEnum + +fun use() { + SomeEnum::class +} + +//INFO:

public final enum class SomeEnum : Enum<SomeEnum> defined in root package

Useless one

diff --git a/idea/testData/editor/quickDoc/OnEnumDeclaration.kt b/idea/testData/editor/quickDoc/OnEnumDeclaration.kt new file mode 100644 index 00000000000..96e55e7ac5b --- /dev/null +++ b/idea/testData/editor/quickDoc/OnEnumDeclaration.kt @@ -0,0 +1,6 @@ +/** + * Useless one + */ +enum class SomeEnum + +//INFO:
public final enum class SomeEnum : Enum<SomeEnum> defined in root package

Useless one

diff --git a/idea/testData/editor/quickDoc/OnEnumUsage.kt b/idea/testData/editor/quickDoc/OnEnumUsage.kt new file mode 100644 index 00000000000..6ccfc81e43a --- /dev/null +++ b/idea/testData/editor/quickDoc/OnEnumUsage.kt @@ -0,0 +1,12 @@ +/** + * Enum of 1, 2 + */ +enum class SomeEnum(val i: Int) { + One(1), Two(2); +} + +fun use() { + SomeEnum.One +} + +//INFO:
public final enum class SomeEnum : Enum<SomeEnum> defined in root package

Enum of 1, 2

diff --git a/idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt b/idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt new file mode 100644 index 00000000000..cf38cac14f0 --- /dev/null +++ b/idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt @@ -0,0 +1,11 @@ +enum class E { + A +} + +fun use() { + E.valueOf("A") +} + + +//INFO: public final fun valueOf(value: String): E defined in E

Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)

+//INFO:
Throws:
IllegalArgumentException - if this enum type has no constant with the specified name
diff --git a/idea/testData/editor/quickDoc/OnEnumValuesFunction.kt b/idea/testData/editor/quickDoc/OnEnumValuesFunction.kt new file mode 100644 index 00000000000..ed70854ab83 --- /dev/null +++ b/idea/testData/editor/quickDoc/OnEnumValuesFunction.kt @@ -0,0 +1,9 @@ +enum class E { + +} + +fun use() { + E.values() +} + +//INFO: public final fun values(): Array<E> defined in E

Returns an array containing the constants of this enum type, in the order they're declared. This method may be used to iterate over the constants.

diff --git a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java index c8c6bbb17fd..16afaf5e1bc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/editor/quickDoc/QuickDocProviderTestGenerated.java @@ -144,6 +144,36 @@ public class QuickDocProviderTestGenerated extends AbstractQuickDocProviderTest doTest(fileName); } + @TestMetadata("OnEnumClassReference.kt") + public void testOnEnumClassReference() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnEnumClassReference.kt"); + doTest(fileName); + } + + @TestMetadata("OnEnumDeclaration.kt") + public void testOnEnumDeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnEnumDeclaration.kt"); + doTest(fileName); + } + + @TestMetadata("OnEnumUsage.kt") + public void testOnEnumUsage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnEnumUsage.kt"); + doTest(fileName); + } + + @TestMetadata("OnEnumValueOfFunction.kt") + public void testOnEnumValueOfFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt"); + doTest(fileName); + } + + @TestMetadata("OnEnumValuesFunction.kt") + public void testOnEnumValuesFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnEnumValuesFunction.kt"); + doTest(fileName); + } + @TestMetadata("OnFunctionDeclarationWithPackage.kt") public void testOnFunctionDeclarationWithPackage() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/quickDoc/OnFunctionDeclarationWithPackage.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 84e87bcbfe3..36704fcf13c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * 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. diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 7f53fedfd43..4ff2f854575 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * 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.