KDoc link parsing rewrite.

Support qualified names immediately after tag (@see or @param). Detect whether a tag is followed by a reference immediately while lexing, remove TEXT_OR_LINK token type. Remove duplicate nested KDocLink nodes from the PSI structure.
This commit is contained in:
Dmitry Jemerov
2015-02-06 12:48:20 +01:00
parent cc5edc332d
commit 70cf3e9c60
21 changed files with 250 additions and 205 deletions
@@ -5,6 +5,8 @@ import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.text.CharArrayUtil;
import java.lang.Character;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag;
%%
@@ -43,6 +45,7 @@ import java.lang.Character;
%state LINE_BEGINNING
%state CONTENTS_BEGINNING
%state TAG_BEGINNING
%state TAG_TEXT_BEGINNING
%state CONTENTS
WHITE_SPACE_CHAR =[\ \t\f\n\r]
@@ -52,9 +55,10 @@ DIGIT=[0-9]
ALPHA=[:jletter:]
TAG_NAME={ALPHA}({ALPHA}|{DIGIT})*
IDENTIFIER={ALPHA}({ALPHA}|{DIGIT}|".")*
CODE_LINK_START={ALPHA}
CODE_LINK_CHAR={ALPHA}|{DIGIT}|[\.]
CODE_LINK=\[{CODE_LINK_START}{CODE_LINK_CHAR}*\]
QUALIFIED_NAME_START={ALPHA}
QUALIFIED_NAME_CHAR={ALPHA}|{DIGIT}|[\.]
QUALIFIED_NAME={QUALIFIED_NAME_START}{QUALIFIED_NAME_CHAR}*
CODE_LINK=\[{QUALIFIED_NAME}\]
%%
@@ -67,8 +71,11 @@ CODE_LINK=\[{CODE_LINK_START}{CODE_LINK_CHAR}*\]
<LINE_BEGINNING> "*"+ { yybegin(CONTENTS_BEGINNING);
return KDocTokens.LEADING_ASTERISK; }
<CONTENTS_BEGINNING> "@"{TAG_NAME} { yybegin(TAG_BEGINNING);
return KDocTokens.TAG_NAME; }
<CONTENTS_BEGINNING> "@"{TAG_NAME} {
KDocKnownTag tag = KDocKnownTag.findByTagName(zzBuffer.subSequence(zzStartRead, zzMarkedPos));
yybegin(tag != null && tag.isReferenceRequired() ? TAG_BEGINNING : TAG_TEXT_BEGINNING);
return KDocTokens.TAG_NAME;
}
<TAG_BEGINNING> {
{WHITE_SPACE_CHAR}+ {
@@ -87,9 +94,9 @@ CODE_LINK=\[{CODE_LINK_START}{CODE_LINK_CHAR}*\]
/* Example: @param aaa The value of aaa
^^^
*/
{IDENTIFIER} {
{QUALIFIED_NAME} {
yybegin(CONTENTS);
return KDocTokens.TEXT_OR_LINK;
return KDocTokens.MARKDOWN_LINK;
}
. {
@@ -98,6 +105,26 @@ CODE_LINK=\[{CODE_LINK_START}{CODE_LINK_CHAR}*\]
}
}
<TAG_TEXT_BEGINNING> {
{WHITE_SPACE_CHAR}+ {
if (yytextContainLineBreaks()) {
yybegin(LINE_BEGINNING);
}
return TokenType.WHITE_SPACE;
}
/* Example: @return[x] The return value of function x
^^^
*/
{CODE_LINK} { yybegin(CONTENTS);
return KDocTokens.MARKDOWN_LINK; }
. {
yybegin(CONTENTS);
return KDocTokens.TEXT;
}
}
<LINE_BEGINNING, CONTENTS_BEGINNING, CONTENTS> {
{WHITE_SPACE_CHAR}+ {
if (yytextContainLineBreaks()) {
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.idea.JetLanguage;
import org.jetbrains.kotlin.kdoc.parser.KDocLinkParser;
import org.jetbrains.kotlin.kdoc.parser.KDocParser;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocImpl;
import org.jetbrains.kotlin.lexer.JetLexer;
public interface KDocTokens {
ILazyParseableElementType KDOC = new ILazyParseableElementType("KDoc", JetLanguage.INSTANCE) {
@@ -57,28 +56,16 @@ public interface KDocTokens {
KDocToken TEXT = new KDocToken("KDOC_TEXT");
/**
* First word following the tag name (@xxx). Depending on the tag name, this can be
* either a link (@param xxx) or just a plain text word (@since version).
* We understand which one it is during parsing.
*/
KDocToken TEXT_OR_LINK = new KDocToken("KDOC_TEXT_OR_LINK");
KDocToken TAG_NAME = new KDocToken("KDOC_TAG_NAME");
ILazyParseableElementType MARKDOWN_LINK = new ILazyParseableElementType("KDOC_MARKDOWN_LINK", JetLanguage.INSTANCE) {
@Override
public ASTNode parseContents(ASTNode chameleon) {
PsiElement parentElement = chameleon.getTreeParent().getPsi();
Project project = parentElement.getProject();
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, new JetLexer(), getLanguage(),
chameleon.getText());
PsiParser parser = new KDocLinkParser();
return parser.parse(this, builder).getFirstChildNode();
return KDocLinkParser.OBJECT$.parseMarkdownLink(this, chameleon);
}
};
KDocToken MARKDOWN_ESCAPED_CHAR = new KDocToken("KDOC_MARKDOWN_ESCAPED_CHAR");
TokenSet KDOC_HIGHLIGHT_TOKENS = TokenSet.create(START, END, LEADING_ASTERISK, TEXT, MARKDOWN_LINK, MARKDOWN_ESCAPED_CHAR, TEXT_OR_LINK);
TokenSet CONTENT_TOKENS = TokenSet.create(TEXT, TAG_NAME, MARKDOWN_LINK, MARKDOWN_ESCAPED_CHAR, TEXT_OR_LINK);
TokenSet KDOC_HIGHLIGHT_TOKENS = TokenSet.create(START, END, LEADING_ASTERISK, TEXT, MARKDOWN_LINK, MARKDOWN_ESCAPED_CHAR);
TokenSet CONTENT_TOKENS = TokenSet.create(TEXT, TAG_NAME, MARKDOWN_LINK, MARKDOWN_ESCAPED_CHAR);
}
@@ -1,20 +1,4 @@
/*
* Copyright 2010-2015 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.
*/
/* The following code was generated by JFlex 1.4.3 on 2/4/15 7:15 PM */
/* The following code was generated by JFlex 1.4.3 on 2/6/15 12:23 PM */
package org.jetbrains.kotlin.kdoc.lexer;
@@ -23,12 +7,14 @@ import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.text.CharArrayUtil;
import java.lang.Character;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 2/4/15 7:15 PM from the specification file
* on 2/6/15 12:23 PM from the specification file
* <tt>/Users/yole/jetbrains/kotlin/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex</tt>
*/
class _KDocLexer implements FlexLexer {
@@ -38,8 +24,9 @@ class _KDocLexer implements FlexLexer {
/** lexical states */
public static final int CONTENTS_BEGINNING = 4;
public static final int LINE_BEGINNING = 2;
public static final int CONTENTS = 8;
public static final int CONTENTS = 10;
public static final int YYINITIAL = 0;
public static final int TAG_TEXT_BEGINNING = 8;
public static final int TAG_BEGINNING = 6;
/**
@@ -49,7 +36,7 @@ class _KDocLexer implements FlexLexer {
* l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2, 3, 3, 4, 4
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
};
/**
@@ -129,12 +116,12 @@ class _KDocLexer implements FlexLexer {
private static final int [] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\5\0\3\1\1\2\1\3\1\2\1\4\3\2\1\5"+
"\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";
private static int [] zzUnpackAction() {
int [] result = new int[31];
int [] result = new int[32];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@@ -160,12 +147,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\101\0\150\0\165\0\202\0\217\0\133\0\234\0\101"+
"\0\251\0\266\0\303\0\133\0\320\0\101\0\133\0\335"+
"\0\101\0\352\0\367\0\101\0\u0104\0\101\0\101";
"\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";
private static int [] zzUnpackRowMap() {
int [] result = new int[31];
int [] result = new int[32];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@@ -188,21 +175,22 @@ class _KDocLexer implements FlexLexer {
private static final int [] ZZ_TRANS = zzUnpackTrans();
private static final String ZZ_TRANS_PACKED_0 =
"\7\6\1\7\1\10\1\6\1\0\2\6\1\11\1\12"+
"\3\11\1\13\2\11\1\14\1\11\1\12\1\15\2\11"+
"\1\12\3\11\1\13\2\11\1\16\1\17\1\12\1\15"+
"\1\11\1\20\1\21\1\20\1\22\1\20\1\23\2\20"+
"\1\24\1\20\1\21\2\20\1\11\1\12\3\11\1\13"+
"\2\11\1\16\1\11\1\12\1\15\1\11\25\0\1\25"+
"\13\0\1\26\1\27\5\0\1\12\10\0\1\12\5\0"+
"\1\30\20\0\1\26\1\14\11\0\2\31\11\0\1\32"+
"\12\0\1\21\10\0\1\21\4\0\3\22\13\0\1\33"+
"\21\0\1\34\6\0\3\30\1\0\1\35\10\0\2\32"+
"\13\0\3\33\1\0\1\36\6\0\5\37\1\0\6\37"+
"\7\7\1\10\1\11\1\7\1\0\2\7\1\12\1\13"+
"\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\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";
private static int [] zzUnpackTrans() {
int [] result = new int[273];
int [] result = new int[286];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
@@ -243,11 +231,11 @@ class _KDocLexer implements FlexLexer {
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\5\0\1\11\2\1\1\11\6\1\1\11\4\1\1\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";
private static int [] zzUnpackAttribute() {
int [] result = new int[31];
int [] result = new int[32];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@@ -574,6 +562,12 @@ class _KDocLexer implements FlexLexer {
zzMarkedPos = zzMarkedPosL;
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 10:
{ KDocKnownTag tag = KDocKnownTag.findByTagName(zzBuffer.subSequence(zzStartRead, zzMarkedPos));
yybegin(tag != null && tag.isReferenceRequired() ? TAG_BEGINNING : TAG_TEXT_BEGINNING);
return KDocTokens.TAG_NAME;
}
case 14: break;
case 3:
{ if (yytextContainLineBreaks()) {
yybegin(LINE_BEGINNING);
@@ -583,16 +577,11 @@ class _KDocLexer implements FlexLexer {
return KDocTokens.TEXT; // internal white space
}
}
case 14: break;
case 15: break;
case 11:
{ yybegin(CONTENTS_BEGINNING);
return KDocTokens.START;
}
case 15: break;
case 7:
{ yybegin(CONTENTS);
return KDocTokens.TEXT_OR_LINK;
}
case 16: break;
case 8:
{ if (isLastToken()) return KDocTokens.END;
@@ -623,24 +612,24 @@ class _KDocLexer implements FlexLexer {
return KDocTokens.MARKDOWN_LINK;
}
case 21: break;
case 10:
{ yybegin(TAG_BEGINNING);
return KDocTokens.TAG_NAME;
}
case 22: break;
case 1:
{ return TokenType.BAD_CHARACTER;
}
case 23: break;
case 22: break;
case 9:
{ yybegin(CONTENTS);
return KDocTokens.MARKDOWN_ESCAPED_CHAR;
}
case 24: break;
case 23: break;
case 2:
{ yybegin(CONTENTS);
return KDocTokens.TEXT;
}
case 24: break;
case 7:
{ yybegin(CONTENTS);
return KDocTokens.MARKDOWN_LINK;
}
case 25: break;
case 4:
{ yybegin(CONTENTS_BEGINNING);
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.kdoc.parser;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag;
@@ -24,6 +23,5 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag;
public class KDocElementTypes {
public static final KDocElementType KDOC_SECTION = new KDocElementType("KDOC_SECTION", KDocSection.class);
public static final KDocElementType KDOC_TAG = new KDocElementType("KDOC_TAG", KDocTag.class);
public static final KDocElementType KDOC_LINK = new KDocElementType("KDOC_LINK", KDocLink.class);
public static final KDocElementType KDOC_NAME = new KDocElementType("KDOC_NAME", KDocName.class);
}
@@ -16,13 +16,15 @@
package org.jetbrains.kotlin.kdoc.parser;
import com.intellij.openapi.util.text.StringUtil;
public enum KDocKnownTag {
AUTHOR(false, false),
THROWS(true, false),
EXCEPTION(true, false),
PARAM(true, false),
RETURN(false, false),
SEE(false, false),
SEE(true, false),
SINCE(false, false),
CONSTRUCTOR(false, true),
PROPERTY(true, true);
@@ -43,12 +45,12 @@ public enum KDocKnownTag {
return startsSection;
}
public static KDocKnownTag findByTagName(String tagName) {
if (tagName.startsWith("@")) {
tagName = tagName.substring(1);
public static KDocKnownTag findByTagName(CharSequence tagName) {
if (StringUtil.startsWith(tagName, "@")) {
tagName = tagName.subSequence(1, tagName.length());
}
try {
return valueOf(tagName.toUpperCase());
return valueOf(tagName.toString().toUpperCase());
}
catch (IllegalArgumentException ignored) {
}
@@ -21,25 +21,53 @@ import com.intellij.psi.tree.IElementType
import com.intellij.lang.PsiBuilder
import com.intellij.lang.ASTNode
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.lexer.JetLexer
import com.intellij.lang.PsiBuilderFactory
/**
* Parses the contents of a Markdown link in KDoc. Uses the standard Kotlin lexer.
*/
class KDocLinkParser(): PsiParser {
class object {
public fun parseMarkdownLink(root: IElementType, chameleon: ASTNode): ASTNode {
val parentElement = chameleon.getTreeParent().getPsi()
val project = parentElement.getProject()
val builder = PsiBuilderFactory.getInstance().createBuilder(project,
chameleon,
JetLexer(),
root.getLanguage(),
chameleon.getText())
val parser = KDocLinkParser()
return parser.parse(root, builder).getFirstChildNode()
}
}
override fun parse(root: IElementType, builder: PsiBuilder): ASTNode {
val rootMarker = builder.mark()
if (builder.getTokenType() == JetTokens.LBRACKET) {
val hasLBracket = builder.getTokenType() == JetTokens.LBRACKET
if (hasLBracket) {
builder.advanceLexer()
}
parseQualifiedName(builder)
if (!builder.eof() && builder.getTokenType() != JetTokens.RBRACKET) {
builder.error("Closing bracket expected")
while (!builder.eof() && builder.getTokenType() != JetTokens.RBRACKET) {
if (hasLBracket) {
if (!builder.eof() && builder.getTokenType() != JetTokens.RBRACKET) {
builder.error("Closing bracket expected")
while (!builder.eof() && builder.getTokenType() != JetTokens.RBRACKET) {
builder.advanceLexer()
}
}
if (builder.getTokenType() == JetTokens.RBRACKET) {
builder.advanceLexer()
}
}
if (builder.getTokenType() == JetTokens.RBRACKET) {
builder.advanceLexer()
else {
if (!builder.eof()) {
builder.error("Expression expected");
while (!builder.eof()) {
builder.advanceLexer();
}
}
}
rootMarker.done(root)
return builder.getTreeBuilt()
@@ -38,11 +38,6 @@ public class KDocParser implements PsiParser {
if (builder.getTokenType() == KDocTokens.TAG_NAME) {
currentSectionMarker = parseTag(builder, currentSectionMarker);
}
else if (builder.getTokenType() == KDocTokens.MARKDOWN_LINK) {
PsiBuilder.Marker linkStart = builder.mark();
builder.advanceLexer();
linkStart.done(KDocElementTypes.KDOC_LINK);
}
else if (builder.getTokenType() == KDocTokens.END) {
if (currentSectionMarker != null) {
currentSectionMarker.done(KDocElementTypes.KDOC_SECTION);
@@ -72,23 +67,8 @@ public class KDocParser implements PsiParser {
PsiBuilder.Marker tagStart = builder.mark();
builder.advanceLexer();
if (knownTag != null && knownTag.isReferenceRequired() && builder.getTokenType() == KDocTokens.TEXT_OR_LINK) {
PsiBuilder.Marker referenceMarker = builder.mark();
PsiBuilder.Marker nameMarker = builder.mark();
builder.advanceLexer();
nameMarker.done(KDocElementTypes.KDOC_NAME);
referenceMarker.done(KDocElementTypes.KDOC_LINK);
}
while (!builder.eof() && !isAtEndOfTag(builder)) {
if (builder.getTokenType() == KDocTokens.MARKDOWN_LINK) {
PsiBuilder.Marker linkStart = builder.mark();
builder.advanceLexer();
linkStart.done(KDocElementTypes.KDOC_LINK);
}
else {
builder.advanceLexer();
}
builder.advanceLexer();
}
tagStart.done(KDocElementTypes.KDOC_TAG);
return currentSectionMarker;
@@ -62,7 +62,7 @@ public open class KDocTag(node: ASTNode) : KDocElementImpl(node) {
private fun hasSubject(contentChildren: List<ASTNode>): Boolean {
if (knownTag?.isReferenceRequired() ?: false) {
return contentChildren.firstOrNull()?.getElementType() == KDocElementTypes.KDOC_LINK;
return contentChildren.firstOrNull()?.getElementType() == KDocTokens.MARKDOWN_LINK
}
return false
}
@@ -88,7 +88,7 @@ public open class KDocTag(node: ASTNode) : KDocElementImpl(node) {
}
for (node in children) {
val type = node.getElementType()
if (KDocTokens.CONTENT_TOKENS.contains(type) || type == KDocElementTypes.KDOC_LINK) {
if (KDocTokens.CONTENT_TOKENS.contains(type)) {
contentStarted = true
builder.append(if (afterAsterisk) StringUtil.trimLeading(node.getText()) else node.getText())
afterAsterisk = false
+10 -12
View File
@@ -7,12 +7,11 @@ JetFile: Markdown.kt
KDOC_SECTION
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('WikiLink')
PsiElement(RBRACKET)(']')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('WikiLink')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
@@ -21,12 +20,11 @@ JetFile: Markdown.kt
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' [')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('DoubleQuotedLink')
PsiElement(RBRACKET)(']')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('DoubleQuotedLink')
PsiElement(RBRACKET)(']')
PsiElement(KDOC_TEXT)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
@@ -7,51 +7,48 @@ JetFile: MarkdownLinkWithError.kt
KDOC_SECTION
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
KDOC_NAME
KDOC_NAME
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('B')
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('C')
PsiErrorElement:Closing bracket expected
<empty list>
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('B')
PsiElement(DOT)('.')
PsiElement(RBRACKET)(']')
PsiElement(IDENTIFIER)('C')
PsiErrorElement:Closing bracket expected
<empty list>
PsiElement(RANGE)('..')
PsiElement(DOT)('.')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' [....]')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiErrorElement:Closing bracket expected
<empty list>
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('B')
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('C')
PsiElement(RBRACKET)(']')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiErrorElement:Closing bracket expected
<empty list>
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('B')
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('C')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiErrorElement:Identifier expected
<empty list>
PsiElement(RBRACKET)(']')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiErrorElement:Identifier expected
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
@@ -7,42 +7,39 @@ JetFile: MarkdownQualifiedName.kt
KDOC_SECTION
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
KDOC_NAME
KDOC_NAME
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('B')
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('C')
PsiElement(RBRACKET)(']')
PsiElement(IDENTIFIER)('B')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('C')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' [')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
KDOC_NAME
KDOC_NAME
PsiElement(IDENTIFIER)('System')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('out')
PsiElement(RBRACKET)(']')
PsiElement(IDENTIFIER)('System')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('out')
PsiElement(RBRACKET)(']')
PsiElement(KDOC_TEXT)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
KDOC_NAME
KDOC_NAME
PsiElement(IDENTIFIER)('System')
PsiElement(DOT)('.')
PsiElement(in)('in')
PsiElement(RBRACKET)(']')
PsiElement(IDENTIFIER)('System')
PsiElement(DOT)('.')
PsiElement(in)('in')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
+2 -2
View File
@@ -10,9 +10,9 @@ JetFile: ParamTag.kt
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@param')
PsiWhiteSpace(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(KDOC_TEXT_OR_LINK)('a')
PsiElement(IDENTIFIER)('a')
PsiElement(KDOC_TEXT)(' The description of a.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
@@ -8,8 +8,8 @@ JetFile: ParamTagAtStart.kt
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@param')
PsiWhiteSpace(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(KDOC_TEXT_OR_LINK)('a')
PsiElement(IDENTIFIER)('a')
PsiElement(KDOC_TEXT)(' this is a ')
PsiElement(KDOC_END)('*/')
@@ -10,19 +10,17 @@ JetFile: ReturnWithBrackets.kt
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@return')
PsiWhiteSpace(' ')
PsiElement(KDOC_TEXT_OR_LINK)('This')
PsiElement(KDOC_TEXT)(' is not a reference')
PsiElement(KDOC_TEXT)('This is not a reference')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@return')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('x')
PsiElement(RBRACKET)(']')
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('x')
PsiElement(RBRACKET)(']')
PsiElement(KDOC_TEXT)(' This is a reference')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
+5 -6
View File
@@ -13,9 +13,9 @@ JetFile: Sections.kt
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@param')
PsiWhiteSpace(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(KDOC_TEXT_OR_LINK)('T')
PsiElement(IDENTIFIER)('T')
PsiElement(KDOC_TEXT)(' a type parameter.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
@@ -24,17 +24,16 @@ JetFile: Sections.kt
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@constructor')
PsiWhiteSpace(' ')
PsiElement(KDOC_TEXT_OR_LINK)('This')
PsiElement(KDOC_TEXT)(' is the doc comment for the primary constructor.')
PsiElement(KDOC_TEXT)('This is the doc comment for the primary constructor.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@param')
PsiWhiteSpace(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
KDOC_NAME
PsiElement(KDOC_TEXT_OR_LINK)('a')
PsiElement(IDENTIFIER)('a')
PsiElement(KDOC_TEXT)(' a constructor parameter.')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
+3
View File
@@ -0,0 +1,3 @@
/**
* @see Foo.bar
*/
+20
View File
@@ -0,0 +1,20 @@
JetFile: SeeLink.kt
PACKAGE_DIRECTIVE
<empty list>
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
KDOC_SECTION
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@see')
PsiWhiteSpace(' ')
KDOC_MARKDOWN_LINK
KDOC_NAME
KDOC_NAME
PsiElement(IDENTIFIER)('Foo')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('bar')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
+2 -3
View File
@@ -10,14 +10,13 @@ JetFile: TwoTags.kt
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@author')
PsiWhiteSpace(' ')
PsiElement(KDOC_TEXT_OR_LINK)('Dmitry')
PsiElement(KDOC_TEXT)(' Jemerov')
PsiElement(KDOC_TEXT)('Dmitry Jemerov')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_TAG
PsiElement(KDOC_TAG_NAME)('@since')
PsiWhiteSpace(' ')
PsiElement(KDOC_TEXT_OR_LINK)('M12')
PsiElement(KDOC_TEXT)('M12')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
@@ -1127,6 +1127,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("SeeLink.kt")
public void testSeeLink() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/SeeLink.kt");
doParsingTest(fileName);
}
@TestMetadata("Simple.kt")
public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/Simple.kt");
@@ -0,0 +1,12 @@
/**
* @see Foo.ba<caret>r
*/
fun xyzzy() {
}
class Foo {
fun bar() {
}
}
// REF: (in Foo).bar()
@@ -17,10 +17,9 @@
package org.jetbrains.kotlin.idea.kdoc;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.InnerTestClasses;
import org.jetbrains.kotlin.idea.resolve.AbstractReferenceResolveTest;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.idea.resolve.AbstractReferenceResolveTest;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
@@ -79,6 +78,12 @@ public class KdocResolveTestGenerated extends AbstractReferenceResolveTest {
doTest(fileName);
}
@TestMetadata("SeeReference.kt")
public void testSeeReference() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/SeeReference.kt");
doTest(fileName);
}
@TestMetadata("TypeParamReference.kt")
public void testTypeParamReference() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/TypeParamReference.kt");