diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex
index e7221fb980b..f798bd2dd7c 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex
+++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex
@@ -88,14 +88,14 @@ CODE_LINK=\[{QUALIFIED_NAME}\]
/* Example: @return[x] The return value of function x
^^^
*/
- {CODE_LINK} { yybegin(CONTENTS);
+ {CODE_LINK} { yybegin(TAG_TEXT_BEGINNING);
return KDocTokens.MARKDOWN_LINK; }
/* Example: @param aaa The value of aaa
^^^
*/
{QUALIFIED_NAME} {
- yybegin(CONTENTS);
+ yybegin(TAG_TEXT_BEGINNING);
return KDocTokens.MARKDOWN_LINK;
}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/_KDocLexer.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/_KDocLexer.java
index 0772ff9bafa..1365b992e75 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/_KDocLexer.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/_KDocLexer.java
@@ -1,4 +1,4 @@
-/* The following code was generated by JFlex 1.4.3 on 2/6/15 12:23 PM */
+/* The following code was generated by JFlex 1.4.3 on 3/5/15 7:51 PM */
package org.jetbrains.kotlin.kdoc.lexer;
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag;
/**
* This class is a scanner generated by
* JFlex 1.4.3
- * on 2/6/15 12:23 PM from the specification file
+ * on 3/5/15 7:51 PM from the specification file
* /Users/yole/jetbrains/kotlin/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex
*/
class _KDocLexer implements FlexLexer {
@@ -117,11 +117,11 @@ class _KDocLexer implements FlexLexer {
private static final String ZZ_ACTION_PACKED_0 =
"\6\0\3\1\1\2\1\3\1\2\1\4\3\2\1\5"+
- "\1\6\1\7\2\5\1\0\1\10\2\0\1\11\1\12"+
- "\1\0\1\13\1\0\1\14\1\15";
+ "\1\6\1\7\3\5\1\0\1\10\2\0\1\11\1\12"+
+ "\2\0\1\13\1\0\1\14\1\15\1\16";
private static int [] zzUnpackAction() {
- int [] result = new int[32];
+ int [] result = new int[35];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@@ -148,11 +148,12 @@ class _KDocLexer implements FlexLexer {
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\15\0\32\0\47\0\64\0\101\0\116\0\133"+
"\0\150\0\116\0\165\0\202\0\217\0\234\0\150\0\251"+
- "\0\116\0\266\0\303\0\320\0\150\0\335\0\116\0\150"+
- "\0\352\0\116\0\367\0\u0104\0\116\0\u0111\0\116\0\116";
+ "\0\116\0\266\0\303\0\320\0\150\0\335\0\352\0\116"+
+ "\0\150\0\367\0\116\0\u0104\0\u0111\0\u011e\0\116\0\u012b"+
+ "\0\116\0\116\0\116";
private static int [] zzUnpackRowMap() {
- int [] result = new int[32];
+ int [] result = new int[35];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@@ -179,18 +180,18 @@ class _KDocLexer implements FlexLexer {
"\3\12\1\14\2\12\1\15\1\12\1\13\1\16\2\12"+
"\1\13\3\12\1\14\2\12\1\17\1\20\1\13\1\16"+
"\1\12\1\21\1\22\1\21\1\23\1\21\1\24\2\21"+
- "\1\25\1\21\1\22\3\21\1\22\3\21\1\24\2\21"+
+ "\1\25\1\21\1\22\3\21\1\22\3\21\1\26\2\21"+
"\1\25\1\21\1\22\2\21\1\12\1\13\3\12\1\14"+
- "\2\12\1\17\1\12\1\13\1\16\1\12\25\0\1\26"+
- "\13\0\1\27\1\30\5\0\1\13\10\0\1\13\5\0"+
- "\1\31\20\0\1\27\1\15\11\0\2\32\11\0\1\33"+
- "\12\0\1\22\10\0\1\22\4\0\3\23\13\0\1\34"+
- "\21\0\1\35\6\0\3\31\1\0\1\36\10\0\2\33"+
- "\13\0\3\34\1\0\1\37\6\0\5\40\1\0\6\40"+
- "\1\0";
+ "\2\12\1\17\1\12\1\13\1\16\1\12\25\0\1\27"+
+ "\13\0\1\30\1\31\5\0\1\13\10\0\1\13\5\0"+
+ "\1\32\20\0\1\30\1\15\11\0\2\33\11\0\1\34"+
+ "\12\0\1\22\10\0\1\22\4\0\3\23\13\0\1\35"+
+ "\14\0\1\36\21\0\1\37\6\0\3\32\1\0\1\40"+
+ "\10\0\2\34\13\0\3\35\1\0\1\41\10\0\3\36"+
+ "\1\0\1\42\6\0\5\43\1\0\6\43\1\0";
private static int [] zzUnpackTrans() {
- int [] result = new int[286];
+ int [] result = new int[312];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
@@ -231,11 +232,11 @@ class _KDocLexer implements FlexLexer {
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
- "\6\0\1\11\2\1\1\11\6\1\1\11\4\1\1\0"+
- "\1\11\2\0\1\11\1\1\1\0\1\11\1\0\2\11";
+ "\6\0\1\11\2\1\1\11\6\1\1\11\5\1\1\0"+
+ "\1\11\2\0\1\11\1\1\2\0\1\11\1\0\3\11";
private static int [] zzUnpackAttribute() {
- int [] result = new int[32];
+ int [] result = new int[35];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@@ -567,7 +568,7 @@ class _KDocLexer implements FlexLexer {
yybegin(tag != null && tag.isReferenceRequired() ? TAG_BEGINNING : TAG_TEXT_BEGINNING);
return KDocTokens.TAG_NAME;
}
- case 14: break;
+ case 15: break;
case 3:
{ if (yytextContainLineBreaks()) {
yybegin(LINE_BEGINNING);
@@ -577,65 +578,70 @@ class _KDocLexer implements FlexLexer {
return KDocTokens.TEXT; // internal white space
}
}
- case 15: break;
+ case 16: break;
case 11:
{ yybegin(CONTENTS_BEGINNING);
return KDocTokens.START;
}
- case 16: break;
+ case 17: break;
case 8:
{ if (isLastToken()) return KDocTokens.END;
else return KDocTokens.TEXT;
}
- case 17: break;
+ case 18: break;
case 5:
{ yybegin(CONTENTS);
return KDocTokens.TEXT;
}
- case 18: break;
+ case 19: break;
+ case 12:
+ { yybegin(TAG_TEXT_BEGINNING);
+ return KDocTokens.MARKDOWN_LINK;
+ }
+ case 20: break;
+ case 7:
+ { yybegin(TAG_TEXT_BEGINNING);
+ return KDocTokens.MARKDOWN_LINK;
+ }
+ case 21: break;
case 6:
{ if (yytextContainLineBreaks()) {
yybegin(LINE_BEGINNING);
}
return TokenType.WHITE_SPACE;
}
- case 19: break;
- case 13:
+ case 22: break;
+ case 14:
// lookahead expression with fixed lookahead length
yypushback(1);
{ yybegin(CONTENTS);
return KDocTokens.MARKDOWN_LINK;
}
- case 20: break;
- case 12:
+ case 23: break;
+ case 13:
{ yybegin(CONTENTS);
return KDocTokens.MARKDOWN_LINK;
}
- case 21: break;
+ case 24: break;
case 1:
{ return TokenType.BAD_CHARACTER;
}
- case 22: break;
+ case 25: break;
case 9:
{ yybegin(CONTENTS);
return KDocTokens.MARKDOWN_ESCAPED_CHAR;
}
- case 23: break;
+ case 26: break;
case 2:
{ yybegin(CONTENTS);
return KDocTokens.TEXT;
}
- case 24: break;
- case 7:
- { yybegin(CONTENTS);
- return KDocTokens.MARKDOWN_LINK;
- }
- case 25: break;
+ case 27: break;
case 4:
{ yybegin(CONTENTS_BEGINNING);
return KDocTokens.LEADING_ASTERISK;
}
- case 26: break;
+ case 28: break;
default:
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.kt b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.kt
index 20e36fb5ef4..4b354b479ce 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.kt
@@ -27,4 +27,5 @@ public trait KDoc : PsiComment {
public fun getDefaultSection(): KDocSection
public fun findSectionByName(name: String): KDocSection?
public fun findSectionByTag(tag: KDocKnownTag): KDocSection?
+ public fun findSectionByTag(tag: KDocKnownTag, subjectName: String): KDocSection?
}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.kt
index e0adf734e73..a3432d48324 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.kt
@@ -46,4 +46,9 @@ public class KDocImpl(buffer: CharSequence?) : LazyParseablePsiElement(KDocToken
override fun findSectionByTag(tag: KDocKnownTag): KDocSection? =
findSectionByName(tag.name().toLowerCase())
+
+ override fun findSectionByTag(tag: KDocKnownTag, subjectName: String): KDocSection? =
+ getChildrenOfType().firstOrNull {
+ it.getName() == tag.name().toLowerCase() && it.getSubjectName() == subjectName
+ }
}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.kt b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.kt
index b1eeaba5066..fe277082278 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.kt
@@ -34,6 +34,9 @@ public class KDocSection(node: ASTNode) : KDocTag(node) {
override fun getName(): String? =
(getFirstChild() as? KDocTag)?.getName()
+ override fun getSubjectName(): String? =
+ (getFirstChild() as? KDocTag)?.getSubjectName()
+
override fun getContent(): String =
(getFirstChild() as? KDocTag)?.getContent() ?: super.getContent()
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.kt b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.kt
index f4f097c38b9..7a3cc025176 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.kt
@@ -44,7 +44,7 @@ public open class KDocTag(node: ASTNode) : KDocElementImpl(node) {
* Returns the name of the entity documented by this tag (for example, the name of the parameter
* for the @param tag), or null if this tag does not document any specific entity.
*/
- public fun getSubjectName(): String? = getSubjectLink()?.getLinkText()
+ public open fun getSubjectName(): String? = getSubjectLink()?.getLinkText()
public fun getSubjectLink(): KDocLink? {
val children = childrenAfterTagName()
diff --git a/compiler/testData/psi/kdoc/ParamTag.txt b/compiler/testData/psi/kdoc/ParamTag.txt
index 5b727c6b959..7b7433c7e2e 100644
--- a/compiler/testData/psi/kdoc/ParamTag.txt
+++ b/compiler/testData/psi/kdoc/ParamTag.txt
@@ -13,6 +13,7 @@ JetFile: ParamTag.kt
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(IDENTIFIER)('a')
- PsiElement(KDOC_TEXT)(' The description of a.')
+ PsiWhiteSpace(' ')
+ PsiElement(KDOC_TEXT)('The description of a.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
\ No newline at end of file
diff --git a/compiler/testData/psi/kdoc/ParamTagAtStart.txt b/compiler/testData/psi/kdoc/ParamTagAtStart.txt
index 21feff72191..08caf4c3ac4 100644
--- a/compiler/testData/psi/kdoc/ParamTagAtStart.txt
+++ b/compiler/testData/psi/kdoc/ParamTagAtStart.txt
@@ -11,5 +11,6 @@ JetFile: ParamTagAtStart.kt
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(IDENTIFIER)('a')
- PsiElement(KDOC_TEXT)(' this is a ')
+ PsiWhiteSpace(' ')
+ PsiElement(KDOC_TEXT)('this is a ')
PsiElement(KDOC_END)('*/')
\ No newline at end of file
diff --git a/compiler/testData/psi/kdoc/Sections.txt b/compiler/testData/psi/kdoc/Sections.txt
index e9412e72e33..723fad9988a 100644
--- a/compiler/testData/psi/kdoc/Sections.txt
+++ b/compiler/testData/psi/kdoc/Sections.txt
@@ -16,7 +16,8 @@ JetFile: Sections.kt
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(IDENTIFIER)('T')
- PsiElement(KDOC_TEXT)(' a type parameter.')
+ PsiWhiteSpace(' ')
+ PsiElement(KDOC_TEXT)('a type parameter.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
@@ -34,6 +35,7 @@ JetFile: Sections.kt
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(IDENTIFIER)('a')
- PsiElement(KDOC_TEXT)(' a constructor parameter.')
+ PsiWhiteSpace(' ')
+ PsiElement(KDOC_TEXT)('a constructor parameter.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocFinder.kt b/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocFinder.kt
index 539ccfd0959..323a024dd8d 100644
--- a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocFinder.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocFinder.kt
@@ -16,14 +16,13 @@
package org.jetbrains.kotlin.idea.kdoc
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
-import org.jetbrains.kotlin.resolve.source.PsiSourceElement
-import org.jetbrains.kotlin.psi.JetDeclaration
-import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
+import org.jetbrains.kotlin.kdoc.psi.api.KDoc
+import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
+import org.jetbrains.kotlin.psi.JetDeclaration
+import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
+import org.jetbrains.kotlin.resolve.source.PsiSourceElement
object KDocFinder {
fun findKDoc(declaration: DeclarationDescriptor): KDocTag? {
@@ -44,6 +43,20 @@ object KDocFinder {
}
}
+ if (declaration is PropertyDescriptor) {
+ val containingClassDescriptor = declaration.getContainingDeclaration() as? ClassDescriptor
+ if (containingClassDescriptor != null) {
+ val classKDoc = findKDoc(containingClassDescriptor)?.getParentOfType(false)
+ if (classKDoc != null) {
+ val propertySection = classKDoc.findSectionByTag(KDocKnownTag.PROPERTY,
+ declaration.getName().asString())
+ if (propertySection != null) {
+ return propertySection
+ }
+ }
+ }
+ }
+
if (declaration is CallableDescriptor) {
for (baseDescriptor in declaration.getOverriddenDescriptors()) {
val baseKDoc = findKDoc(baseDescriptor.getOriginal())
diff --git a/idea/testData/kdoc/finder/Property.kt b/idea/testData/kdoc/finder/Property.kt
new file mode 100644
index 00000000000..1c36cd0157a
--- /dev/null
+++ b/idea/testData/kdoc/finder/Property.kt
@@ -0,0 +1,4 @@
+/**
+ * @property xyzzy Doc for property xyzzy
+ */
+class Foo(val xyzzy: String)
diff --git a/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocFinderTest.kt b/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocFinderTest.kt
index 8005c2e6830..6fd80b7edd2 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocFinderTest.kt
+++ b/idea/tests/org/jetbrains/kotlin/idea/kdoc/KDocFinderTest.kt
@@ -55,4 +55,13 @@ public class KDocFinderTest() : LightPlatformCodeInsightFixtureTestCase() {
val doc = KDocFinder.findKDoc(overriddenFunctionDescriptor)
Assert.assertEquals("Doc for method xyzzy", doc!!.getContent())
}
+
+ public fun testProperty() {
+ myFixture.configureByFile(getTestName(false) + ".kt")
+ val declaration = (myFixture.getFile() as JetFile).getDeclarations().single { it.getName() == "Foo" }
+ val descriptor = declaration.resolveToDescriptor() as ClassDescriptor
+ val propertyDescriptor = descriptor.getDefaultType().getMemberScope().getProperties(Name.identifier("xyzzy")).single()
+ val doc = KDocFinder.findKDoc(propertyDescriptor)
+ Assert.assertEquals("Doc for property xyzzy", doc!!.getContent())
+ }
}