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:
@@ -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
|
||||
|
||||
@@ -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)('*/')
|
||||
@@ -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)('*/')
|
||||
@@ -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)('*/')
|
||||
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* @see Foo.bar
|
||||
*/
|
||||
@@ -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)('*/')
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user