From f3763bc2b5fb9fdb35d47f94a5fc447f54cbd67a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 19 Jan 2015 20:54:05 +0100 Subject: [PATCH] some initial PSI for KDoc; changed syntax of links (Markdown style single brackets instead of Wiki style double brackets) --- .../org/jetbrains/kotlin/kdoc/lexer/KDoc.flex | 48 +++- .../kotlin/kdoc/lexer/KDocTokens.java | 16 +- .../kotlin/kdoc/lexer/_KDocLexer.java | 231 ++++++++++-------- .../kotlin/kdoc/parser/KDocElementType.java | 47 ++++ .../kotlin/kdoc/parser/KDocElementTypes.java | 25 ++ .../kotlin/kdoc/parser/KDocKnownTag.java | 48 ++++ .../kotlin/kdoc/parser/KDocParser.java | 54 +++- .../kotlin/kdoc/psi/impl/KDocLink.java | 26 ++ .../kotlin/kdoc/psi/impl/KDocTag.java | 27 ++ .../kotlin/parsing/JetParserDefinition.java | 4 + compiler/testData/psi/kdoc/AtTags.txt | 15 +- compiler/testData/psi/kdoc/Markdown.kt | 6 +- compiler/testData/psi/kdoc/Markdown.txt | 19 +- compiler/testData/psi/kdoc/ParamTag.kt | 3 + compiler/testData/psi/kdoc/ParamTag.txt | 16 ++ .../testData/psi/kdoc/ReturnWithBrackets.kt | 4 + .../testData/psi/kdoc/ReturnWithBrackets.txt | 23 ++ compiler/testData/psi/kdoc/TwoTags.kt | 4 + compiler/testData/psi/kdoc/TwoTags.txt | 22 ++ .../parsing/JetParsingTestGenerated.java | 18 ++ .../jetbrains/kotlin/idea/JetPairMatcher.java | 4 - 21 files changed, 519 insertions(+), 141 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocLink.java create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java create mode 100644 compiler/testData/psi/kdoc/ParamTag.kt create mode 100644 compiler/testData/psi/kdoc/ParamTag.txt create mode 100644 compiler/testData/psi/kdoc/ReturnWithBrackets.kt create mode 100644 compiler/testData/psi/kdoc/ReturnWithBrackets.txt create mode 100644 compiler/testData/psi/kdoc/TwoTags.kt create mode 100644 compiler/testData/psi/kdoc/TwoTags.txt 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 6633bec9601..bafec022e15 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex @@ -42,9 +42,8 @@ import java.lang.Character; %state LINE_BEGINNING %state CONTENTS_BEGINNING +%state TAG_BEGINNING %state CONTENTS -%state CODE -%state CODE2 WHITE_SPACE_CHAR =[\ \t\f\n\r] NOT_WHITE_SPACE_CHAR=[^\ \t\f\n\r] @@ -52,8 +51,10 @@ NOT_WHITE_SPACE_CHAR=[^\ \t\f\n\r] DIGIT=[0-9] ALPHA=[:jletter:] TAG_NAME={ALPHA}({ALPHA}|{DIGIT})* - -MARKDOWN_EMPHASIS=[\*_] +IDENTIFIER={ALPHA}({ALPHA}|{DIGIT}|".")* +CODE_LINK_START={ALPHA} +CODE_LINK_CHAR={ALPHA}|{DIGIT}|[()\-\.<>] +CODE_LINK=\[{CODE_LINK_START}{CODE_LINK_CHAR}*\] %% @@ -66,9 +67,37 @@ MARKDOWN_EMPHASIS=[\*_] "*"+ { yybegin(CONTENTS_BEGINNING); return KDocTokens.LEADING_ASTERISK; } - "@"{TAG_NAME} { yybegin(CONTENTS); + "@"{TAG_NAME} { yybegin(TAG_BEGINNING); return KDocTokens.TAG_NAME; } + { + {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; } + + /* Example: @param aaa The value of aaa + ^^^ + */ + {IDENTIFIER} { + yybegin(CONTENTS); + return KDocTokens.TEXT_OR_LINK; + } + + . { + yybegin(CONTENTS); + return KDocTokens.TEXT; + } +} + { {WHITE_SPACE_CHAR}+ { if (yytextContainLineBreaks()) { @@ -83,10 +112,11 @@ MARKDOWN_EMPHASIS=[\*_] "\\"[\[\]] { yybegin(CONTENTS); return KDocTokens.MARKDOWN_ESCAPED_CHAR; } - "[[" { yybegin(CONTENTS); - return KDocTokens.WIKI_LINK_OPEN; } - "]]" { yybegin(CONTENTS); - return KDocTokens.WIKI_LINK_CLOSE; } + /* We're only interested in parsing links that can become code references, + meaning they contain only identifier characters and characters that can be + used in type declarations. No brackets, backticks, asterisks or anything like that. */ + {CODE_LINK} { yybegin(CONTENTS); + return KDocTokens.MARKDOWN_LINK; } . { yybegin(CONTENTS); return KDocTokens.TEXT; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java index 4d38a3b9d26..4eaf77f4b49 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java @@ -54,12 +54,18 @@ public interface KDocTokens { KDocToken LEADING_ASTERISK = new KDocToken("KDOC_LEADING_ASTERISK"); 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 (@author name). + * 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"); - KDocToken WIKI_LINK_OPEN = new KDocToken("KDOC_WIKI_LINK_OPEN"); - KDocToken WIKI_LINK_CLOSE = new KDocToken("KDOC_WIKI_LINK_CLOSE"); + KDocToken MARKDOWN_LINK = new KDocToken("KDOC_MARKDOWN_LINK"); - KDocToken MARKDOWN_ESCAPED_CHAR = new KDocToken("KDOC_MARKDOWN_ESCAPED_CHAR"); + KDocToken MARKDOWN_ESCAPED_CHAR = new KDocToken("KDOC_MARKDOWN_ESCAPED_CHAR"); - TokenSet KDOC_HIGHLIGHT_TOKENS = TokenSet.create(START, END, LEADING_ASTERISK, TEXT, WIKI_LINK_OPEN, WIKI_LINK_CLOSE, MARKDOWN_ESCAPED_CHAR); - TokenSet CONTENT_TOKENS = TokenSet.create(TEXT, TAG_NAME, WIKI_LINK_OPEN, WIKI_LINK_CLOSE, MARKDOWN_ESCAPED_CHAR); + 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); } 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 9c9e6eef867..e1e48faa690 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/_KDocLexer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/_KDocLexer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -/* The following code was generated by JFlex 1.4.3 on 1/10/15 1:43 PM */ +/* The following code was generated by JFlex 1.4.3 on 1/19/15 8:28 PM */ package org.jetbrains.kotlin.kdoc.lexer; @@ -28,20 +28,19 @@ import java.lang.Character; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 1/10/15 1:43 PM from the specification file - * /Users/udalov/kotlin/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex + * on 1/19/15 8:28 PM from the specification file + * /Users/yole/jetbrains/kotlin/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDoc.flex */ class _KDocLexer implements FlexLexer { /** initial size of the lookahead buffer */ private static final int ZZ_BUFFERSIZE = 16384; /** lexical states */ - public static final int CODE = 8; public static final int CONTENTS_BEGINNING = 4; - public static final int CODE2 = 10; public static final int LINE_BEGINNING = 2; - public static final int CONTENTS = 6; + public static final int CONTENTS = 8; public static final int YYINITIAL = 0; + public static final int TAG_BEGINNING = 6; /** * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l @@ -50,74 +49,74 @@ 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, 4, 4 + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4 }; /** * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\1\1\1\12\1\0\2\1\22\0\1\1\3\0\1\3\5\0"+ - "\1\4\4\0\1\5\12\2\6\0\1\6\32\3\1\11\1\7\1\10"+ - "\1\0\1\3\1\0\32\3\47\0\4\3\4\0\1\3\12\0\1\3"+ - "\4\0\1\3\5\0\27\3\1\0\37\3\1\0\u013f\3\31\0\162\3"+ - "\4\0\14\3\16\0\5\3\11\0\1\3\213\0\1\3\13\0\1\3"+ - "\1\0\3\3\1\0\1\3\1\0\24\3\1\0\54\3\1\0\46\3"+ - "\1\0\5\3\4\0\202\3\10\0\105\3\1\0\46\3\2\0\2\3"+ - "\6\0\20\3\41\0\46\3\2\0\1\3\7\0\47\3\110\0\33\3"+ - "\5\0\3\3\56\0\32\3\5\0\13\3\43\0\2\3\1\0\143\3"+ - "\1\0\1\3\17\0\2\3\7\0\2\3\12\0\3\3\2\0\1\3"+ - "\20\0\1\3\1\0\36\3\35\0\3\3\60\0\46\3\13\0\1\3"+ - "\u0152\0\66\3\3\0\1\3\22\0\1\3\7\0\12\3\43\0\10\3"+ - "\2\0\2\3\2\0\26\3\1\0\7\3\1\0\1\3\3\0\4\3"+ - "\3\0\1\3\36\0\2\3\1\0\3\3\16\0\4\3\21\0\6\3"+ - "\4\0\2\3\2\0\26\3\1\0\7\3\1\0\2\3\1\0\2\3"+ - "\1\0\2\3\37\0\4\3\1\0\1\3\23\0\3\3\20\0\11\3"+ - "\1\0\3\3\1\0\26\3\1\0\7\3\1\0\2\3\1\0\5\3"+ - "\3\0\1\3\22\0\1\3\17\0\2\3\17\0\1\3\23\0\10\3"+ - "\2\0\2\3\2\0\26\3\1\0\7\3\1\0\2\3\1\0\5\3"+ - "\3\0\1\3\36\0\2\3\1\0\3\3\17\0\1\3\21\0\1\3"+ - "\1\0\6\3\3\0\3\3\1\0\4\3\3\0\2\3\1\0\1\3"+ - "\1\0\2\3\3\0\2\3\3\0\3\3\3\0\10\3\1\0\3\3"+ - "\77\0\1\3\13\0\10\3\1\0\3\3\1\0\27\3\1\0\12\3"+ - "\1\0\5\3\46\0\2\3\43\0\10\3\1\0\3\3\1\0\27\3"+ - "\1\0\12\3\1\0\5\3\3\0\1\3\40\0\1\3\1\0\2\3"+ - "\43\0\10\3\1\0\3\3\1\0\27\3\1\0\20\3\46\0\2\3"+ - "\43\0\22\3\3\0\30\3\1\0\11\3\1\0\1\3\2\0\7\3"+ - "\72\0\60\3\1\0\2\3\13\0\10\3\72\0\2\3\1\0\1\3"+ - "\2\0\2\3\1\0\1\3\2\0\1\3\6\0\4\3\1\0\7\3"+ - "\1\0\3\3\1\0\1\3\1\0\1\3\2\0\2\3\1\0\4\3"+ - "\1\0\2\3\11\0\1\3\2\0\5\3\1\0\1\3\25\0\2\3"+ - "\42\0\1\3\77\0\10\3\1\0\42\3\35\0\4\3\164\0\42\3"+ - "\1\0\5\3\1\0\2\3\45\0\6\3\112\0\46\3\12\0\51\3"+ - "\7\0\132\3\5\0\104\3\5\0\122\3\6\0\7\3\1\0\77\3"+ - "\1\0\1\3\1\0\4\3\2\0\7\3\1\0\1\3\1\0\4\3"+ - "\2\0\47\3\1\0\1\3\1\0\4\3\2\0\37\3\1\0\1\3"+ - "\1\0\4\3\2\0\7\3\1\0\1\3\1\0\4\3\2\0\7\3"+ - "\1\0\7\3\1\0\27\3\1\0\37\3\1\0\1\3\1\0\4\3"+ - "\2\0\7\3\1\0\47\3\1\0\23\3\105\0\125\3\14\0\u026c\3"+ - "\2\0\10\3\12\0\32\3\5\0\113\3\3\0\3\3\17\0\15\3"+ - "\1\0\4\3\16\0\22\3\16\0\22\3\16\0\15\3\1\0\3\3"+ - "\17\0\64\3\43\0\1\3\3\0\2\3\103\0\130\3\10\0\51\3"+ - "\127\0\35\3\63\0\36\3\2\0\5\3\u038b\0\154\3\224\0\234\3"+ - "\4\0\132\3\6\0\26\3\2\0\6\3\2\0\46\3\2\0\6\3"+ - "\2\0\10\3\1\0\1\3\1\0\1\3\1\0\1\3\1\0\37\3"+ - "\2\0\65\3\1\0\7\3\1\0\1\3\3\0\3\3\1\0\7\3"+ - "\3\0\4\3\2\0\6\3\4\0\15\3\5\0\3\3\1\0\7\3"+ - "\102\0\2\3\23\0\1\3\34\0\1\3\15\0\1\3\40\0\22\3"+ - "\120\0\1\3\4\0\1\3\2\0\12\3\1\0\1\3\3\0\5\3"+ - "\6\0\1\3\1\0\1\3\1\0\1\3\1\0\4\3\1\0\3\3"+ - "\1\0\7\3\3\0\3\3\5\0\5\3\26\0\44\3\u0e81\0\3\3"+ - "\31\0\11\3\7\0\5\3\2\0\5\3\4\0\126\3\6\0\3\3"+ - "\1\0\137\3\5\0\50\3\4\0\136\3\21\0\30\3\70\0\20\3"+ - "\u0200\0\u19b6\3\112\0\u51a6\3\132\0\u048d\3\u0773\0\u2ba4\3\u215c\0\u012e\3"+ - "\2\0\73\3\225\0\7\3\14\0\5\3\5\0\1\3\1\0\12\3"+ - "\1\0\15\3\1\0\5\3\1\0\1\3\1\0\2\3\1\0\2\3"+ - "\1\0\154\3\41\0\u016b\3\22\0\100\3\2\0\66\3\50\0\15\3"+ - "\66\0\2\3\30\0\3\3\31\0\1\3\6\0\5\3\1\0\207\3"+ - "\7\0\1\3\34\0\32\3\4\0\1\3\1\0\32\3\12\0\132\3"+ - "\3\0\6\3\2\0\6\3\2\0\6\3\2\0\3\3\3\0\2\3"+ - "\3\0\2\3\31\0"; + "\11\0\1\1\1\13\1\0\2\1\22\0\1\1\3\0\1\3\3\0"+ + "\2\5\1\11\2\0\1\5\1\4\1\10\12\2\2\0\1\5\1\0"+ + "\1\5\1\0\1\12\32\3\1\6\1\14\1\7\1\0\1\3\1\0"+ + "\32\3\47\0\4\3\4\0\1\3\12\0\1\3\4\0\1\3\5\0"+ + "\27\3\1\0\37\3\1\0\u013f\3\31\0\162\3\4\0\14\3\16\0"+ + "\5\3\11\0\1\3\213\0\1\3\13\0\1\3\1\0\3\3\1\0"+ + "\1\3\1\0\24\3\1\0\54\3\1\0\46\3\1\0\5\3\4\0"+ + "\202\3\10\0\105\3\1\0\46\3\2\0\2\3\6\0\20\3\41\0"+ + "\46\3\2\0\1\3\7\0\47\3\110\0\33\3\5\0\3\3\56\0"+ + "\32\3\5\0\13\3\43\0\2\3\1\0\143\3\1\0\1\3\17\0"+ + "\2\3\7\0\2\3\12\0\3\3\2\0\1\3\20\0\1\3\1\0"+ + "\36\3\35\0\3\3\60\0\46\3\13\0\1\3\u0152\0\66\3\3\0"+ + "\1\3\22\0\1\3\7\0\12\3\43\0\10\3\2\0\2\3\2\0"+ + "\26\3\1\0\7\3\1\0\1\3\3\0\4\3\3\0\1\3\36\0"+ + "\2\3\1\0\3\3\16\0\4\3\21\0\6\3\4\0\2\3\2\0"+ + "\26\3\1\0\7\3\1\0\2\3\1\0\2\3\1\0\2\3\37\0"+ + "\4\3\1\0\1\3\23\0\3\3\20\0\11\3\1\0\3\3\1\0"+ + "\26\3\1\0\7\3\1\0\2\3\1\0\5\3\3\0\1\3\22\0"+ + "\1\3\17\0\2\3\17\0\1\3\23\0\10\3\2\0\2\3\2\0"+ + "\26\3\1\0\7\3\1\0\2\3\1\0\5\3\3\0\1\3\36\0"+ + "\2\3\1\0\3\3\17\0\1\3\21\0\1\3\1\0\6\3\3\0"+ + "\3\3\1\0\4\3\3\0\2\3\1\0\1\3\1\0\2\3\3\0"+ + "\2\3\3\0\3\3\3\0\10\3\1\0\3\3\77\0\1\3\13\0"+ + "\10\3\1\0\3\3\1\0\27\3\1\0\12\3\1\0\5\3\46\0"+ + "\2\3\43\0\10\3\1\0\3\3\1\0\27\3\1\0\12\3\1\0"+ + "\5\3\3\0\1\3\40\0\1\3\1\0\2\3\43\0\10\3\1\0"+ + "\3\3\1\0\27\3\1\0\20\3\46\0\2\3\43\0\22\3\3\0"+ + "\30\3\1\0\11\3\1\0\1\3\2\0\7\3\72\0\60\3\1\0"+ + "\2\3\13\0\10\3\72\0\2\3\1\0\1\3\2\0\2\3\1\0"+ + "\1\3\2\0\1\3\6\0\4\3\1\0\7\3\1\0\3\3\1\0"+ + "\1\3\1\0\1\3\2\0\2\3\1\0\4\3\1\0\2\3\11\0"+ + "\1\3\2\0\5\3\1\0\1\3\25\0\2\3\42\0\1\3\77\0"+ + "\10\3\1\0\42\3\35\0\4\3\164\0\42\3\1\0\5\3\1\0"+ + "\2\3\45\0\6\3\112\0\46\3\12\0\51\3\7\0\132\3\5\0"+ + "\104\3\5\0\122\3\6\0\7\3\1\0\77\3\1\0\1\3\1\0"+ + "\4\3\2\0\7\3\1\0\1\3\1\0\4\3\2\0\47\3\1\0"+ + "\1\3\1\0\4\3\2\0\37\3\1\0\1\3\1\0\4\3\2\0"+ + "\7\3\1\0\1\3\1\0\4\3\2\0\7\3\1\0\7\3\1\0"+ + "\27\3\1\0\37\3\1\0\1\3\1\0\4\3\2\0\7\3\1\0"+ + "\47\3\1\0\23\3\105\0\125\3\14\0\u026c\3\2\0\10\3\12\0"+ + "\32\3\5\0\113\3\3\0\3\3\17\0\15\3\1\0\4\3\16\0"+ + "\22\3\16\0\22\3\16\0\15\3\1\0\3\3\17\0\64\3\43\0"+ + "\1\3\3\0\2\3\103\0\130\3\10\0\51\3\127\0\35\3\63\0"+ + "\36\3\2\0\5\3\u038b\0\154\3\224\0\234\3\4\0\132\3\6\0"+ + "\26\3\2\0\6\3\2\0\46\3\2\0\6\3\2\0\10\3\1\0"+ + "\1\3\1\0\1\3\1\0\1\3\1\0\37\3\2\0\65\3\1\0"+ + "\7\3\1\0\1\3\3\0\3\3\1\0\7\3\3\0\4\3\2\0"+ + "\6\3\4\0\15\3\5\0\3\3\1\0\7\3\102\0\2\3\23\0"+ + "\1\3\34\0\1\3\15\0\1\3\40\0\22\3\120\0\1\3\4\0"+ + "\1\3\2\0\12\3\1\0\1\3\3\0\5\3\6\0\1\3\1\0"+ + "\1\3\1\0\1\3\1\0\4\3\1\0\3\3\1\0\7\3\3\0"+ + "\3\3\5\0\5\3\26\0\44\3\u0e81\0\3\3\31\0\11\3\7\0"+ + "\5\3\2\0\5\3\4\0\126\3\6\0\3\3\1\0\137\3\5\0"+ + "\50\3\4\0\136\3\21\0\30\3\70\0\20\3\u0200\0\u19b6\3\112\0"+ + "\u51a6\3\132\0\u048d\3\u0773\0\u2ba4\3\u215c\0\u012e\3\2\0\73\3\225\0"+ + "\7\3\14\0\5\3\5\0\1\3\1\0\12\3\1\0\15\3\1\0"+ + "\5\3\1\0\1\3\1\0\2\3\1\0\2\3\1\0\154\3\41\0"+ + "\u016b\3\22\0\100\3\2\0\66\3\50\0\15\3\66\0\2\3\30\0"+ + "\3\3\31\0\1\3\6\0\5\3\1\0\207\3\7\0\1\3\34\0"+ + "\32\3\4\0\1\3\1\0\32\3\12\0\132\3\3\0\6\3\2\0"+ + "\6\3\2\0\6\3\2\0\3\3\3\0\2\3\3\0\2\3\31\0"; /** * Translates characters to character classes @@ -130,11 +129,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\4\5\2\1\0\1\5"+ - "\1\0\1\6\1\7\1\10\1\11\1\12"; + "\5\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\13\1\14"; private static int [] zzUnpackAction() { - int [] result = new int[24]; + int [] result = new int[28]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -159,12 +159,13 @@ class _KDocLexer implements FlexLexer { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\13\0\26\0\41\0\54\0\67\0\102\0\115"+ - "\0\67\0\130\0\143\0\156\0\171\0\204\0\102\0\217"+ - "\0\102\0\67\0\232\0\67\0\67\0\67\0\245\0\67"; + "\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\165\0\133\0\303\0\101\0\133\0\320"+ + "\0\101\0\335\0\101\0\101"; private static int [] zzUnpackRowMap() { - int [] result = new int[24]; + int [] result = new int[28]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -187,17 +188,19 @@ class _KDocLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\4\6\1\7\1\10\4\6\1\0\1\11\1\12\2\11"+ - "\1\13\2\11\1\14\1\15\1\16\1\12\1\11\1\12"+ - "\2\11\1\17\1\11\1\20\1\14\1\15\1\16\1\12"+ - "\1\11\1\12\2\11\1\17\2\11\1\14\1\15\1\16"+ - "\1\12\4\6\1\7\5\6\20\0\1\21\1\22\11\0"+ - "\1\23\7\0\1\12\10\0\1\12\4\0\1\13\1\22"+ - "\15\0\2\24\11\0\1\25\13\0\1\26\4\0\1\27"+ - "\13\0\1\30\10\0\2\27\7\0"; + "\10\6\1\7\1\10\1\6\1\0\1\6\1\11\1\12"+ + "\4\11\1\13\2\11\1\14\1\11\1\12\1\15\1\11"+ + "\1\12\4\11\1\13\2\11\1\16\1\17\1\12\1\15"+ + "\1\20\1\21\1\20\1\22\2\20\1\23\2\20\1\24"+ + "\1\20\1\21\1\20\1\11\1\12\4\11\1\13\2\11"+ + "\1\16\1\11\1\12\1\15\26\0\1\25\13\0\1\26"+ + "\1\27\4\0\1\12\11\0\1\12\4\0\1\30\21\0"+ + "\1\26\1\14\11\0\2\31\10\0\1\32\12\0\1\21"+ + "\11\0\1\21\3\0\3\22\21\0\1\33\5\0\4\30"+ + "\1\0\1\34\7\0\2\32\11\0"; private static int [] zzUnpackTrans() { - int [] result = new int[176]; + int [] result = new int[234]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -238,11 +241,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\7\1\1\0\1\11\1\0"+ - "\3\11\1\1\1\11"; + "\5\0\1\11\2\1\1\11\6\1\1\11\4\1\1\0"+ + "\1\11\2\0\1\11\1\1\2\11"; private static int [] zzUnpackAttribute() { - int [] result = new int[24]; + int [] result = new int[28]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -346,7 +349,7 @@ class _KDocLexer implements FlexLexer { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 1206) { + while (i < 1220) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -578,51 +581,63 @@ class _KDocLexer implements FlexLexer { return KDocTokens.TEXT; // internal white space } } - case 11: break; - case 5: - { if (isLastToken()) return KDocTokens.END; - else return KDocTokens.TEXT; - } - case 12: break; - case 9: - { yybegin(CONTENTS); - return KDocTokens.TAG_NAME; - } case 13: break; case 7: { yybegin(CONTENTS); - return KDocTokens.WIKI_LINK_CLOSE; + return KDocTokens.TEXT_OR_LINK; } case 14: break; case 8: - { yybegin(CONTENTS); - return KDocTokens.WIKI_LINK_OPEN; + { if (isLastToken()) return KDocTokens.END; + else return KDocTokens.TEXT; } case 15: break; - case 10: + case 5: + { yybegin(CONTENTS); + return KDocTokens.TEXT; + } + case 16: break; + case 6: + { if (yytextContainLineBreaks()) { + yybegin(LINE_BEGINNING); + } + return TokenType.WHITE_SPACE; + } + case 17: break; + case 12: + { yybegin(CONTENTS); + return KDocTokens.MARKDOWN_LINK; + } + case 18: break; + case 11: { yybegin(CONTENTS); return KDocTokens.START; } - case 16: break; + case 19: break; + case 10: + { yybegin(TAG_BEGINNING); + return KDocTokens.TAG_NAME; + } + case 20: break; case 1: { return TokenType.BAD_CHARACTER; } - case 17: break; - case 6: + case 21: break; + case 9: { yybegin(CONTENTS); return KDocTokens.MARKDOWN_ESCAPED_CHAR; } - case 18: break; + case 22: break; case 2: { yybegin(CONTENTS); return KDocTokens.TEXT; } - case 19: break; + case 23: break; case 4: { yybegin(CONTENTS_BEGINNING); return KDocTokens.LEADING_ASTERISK; } - case 20: break; + case 24: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java new file mode 100644 index 00000000000..70704187ee7 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.kdoc.parser; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.kotlin.idea.JetLanguage; +import org.jetbrains.kotlin.kdoc.psi.impl.KDocElementImpl; + +import java.lang.reflect.Constructor; + +public class KDocElementType extends IElementType { + private final Constructor myPsiFactory; + + public KDocElementType(String debugName, Class psiClass) { + super(debugName, JetLanguage.INSTANCE); + try { + myPsiFactory = psiClass != null ? psiClass.getConstructor(ASTNode.class) : null; + } catch (NoSuchMethodException e) { + throw new RuntimeException("Must have a constructor with ASTNode"); + } + } + + public KDocElementImpl createPsi(ASTNode node) { + assert node.getElementType() == this; + + try { + return myPsiFactory.newInstance(node); + } catch (Exception e) { + throw new RuntimeException("Error creating psi element for node", e); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java new file mode 100644 index 00000000000..bf3ebd95014 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.kdoc.parser; + +import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink; +import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag; + +public class KDocElementTypes { + public static final KDocElementType KDOC_TAG = new KDocElementType("KDOC_TAG", KDocTag.class); + public static final KDocElementType KDOC_LINK = new KDocElementType("KDOC_LINK", KDocLink.class); +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java new file mode 100644 index 00000000000..9a2acf563e9 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.kdoc.parser; + +public enum KDocKnownTag { + AUTHOR(false), + THROWS(true), + EXCEPTION(true), + PARAM(true), + RETURN(false), + SEE(false), + SINCE(false); + + private final boolean takesReference; + + KDocKnownTag(boolean takesReference) { + this.takesReference = takesReference; + } + + public boolean isReferenceRequired() { + return takesReference; + } + + public static KDocKnownTag findByTagName(String tagName) { + if (tagName.startsWith("@")) { + try { + return valueOf(tagName.substring(1).toUpperCase()); + } + catch (IllegalArgumentException ignored) { + } + } + return null; + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocParser.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocParser.java index 118cb92ee90..f8fcaa5a5b3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocParser.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocParser.java @@ -21,6 +21,7 @@ import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiParser; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; public class KDocParser implements PsiParser { @Override @@ -30,10 +31,61 @@ public class KDocParser implements PsiParser { // todo: parse KDoc tags, markdown, etc... while (!builder.eof()) { - builder.advanceLexer(); + if (builder.getTokenType() == KDocTokens.TAG_NAME) { + parseTag(builder); + } + else if (builder.getTokenType() == KDocTokens.MARKDOWN_LINK) { + PsiBuilder.Marker linkStart = builder.mark(); + builder.advanceLexer(); + linkStart.done(KDocElementTypes.KDOC_LINK); + } + else { + builder.advanceLexer(); + } } rootMarker.done(root); return builder.getTreeBuilt(); } + + private static void parseTag(PsiBuilder builder) { + PsiBuilder.Marker tagStart = builder.mark(); + String tagName = builder.getTokenText(); + KDocKnownTag knownTag = KDocKnownTag.findByTagName(tagName); + builder.advanceLexer(); + + if (knownTag != null && knownTag.isReferenceRequired() && builder.getTokenType() == KDocTokens.TEXT_OR_LINK) { + PsiBuilder.Marker referenceMarker = builder.mark(); + builder.advanceLexer(); + 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(); + } + } + tagStart.done(KDocElementTypes.KDOC_TAG); + } + + private static boolean isAtEndOfTag(PsiBuilder builder) { + if (builder.getTokenType() == KDocTokens.END) { + return true; + } + if (builder.getTokenType() == KDocTokens.LEADING_ASTERISK) { + int lookAheadCount = 1; + if (builder.lookAhead(1) == KDocTokens.TEXT) { + lookAheadCount++; + } + if (builder.lookAhead(lookAheadCount) == KDocTokens.TAG_NAME) { + return true; + } + } + return false; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocLink.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocLink.java new file mode 100644 index 00000000000..b733e0a4b17 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocLink.java @@ -0,0 +1,26 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.kdoc.psi.impl; + +import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; + +public class KDocLink extends KDocElementImpl { + public KDocLink(@NotNull ASTNode node) { + super(node); + } +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java new file mode 100644 index 00000000000..59b2fc1403f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java @@ -0,0 +1,27 @@ +/* + * 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. + */ + +package org.jetbrains.kotlin.kdoc.psi.impl; + +import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; + +public class KDocTag extends KDocElementImpl { + public KDocTag(@NotNull ASTNode node) { + super(node); + } + +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParserDefinition.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParserDefinition.java index 2e64c52ee00..66a812a949f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParserDefinition.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetParserDefinition.java @@ -33,6 +33,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.JetNodeType; import org.jetbrains.kotlin.JetNodeTypes; import org.jetbrains.kotlin.idea.JetLanguage; +import org.jetbrains.kotlin.kdoc.parser.KDocElementType; import org.jetbrains.kotlin.lexer.JetLexer; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.JetFile; @@ -102,6 +103,9 @@ public class JetParserDefinition implements ParserDefinition { elementType == JetNodeTypes.BLOCK_CODE_FRAGMENT) { return new ASTWrapperPsiElement(astNode); } + else if (elementType instanceof KDocElementType) { + return ((KDocElementType) elementType).createPsi(astNode); + } else { return ((JetNodeType) elementType).createPsi(astNode); } diff --git a/compiler/testData/psi/kdoc/AtTags.txt b/compiler/testData/psi/kdoc/AtTags.txt index 7a890defcbe..88fb41a42d6 100644 --- a/compiler/testData/psi/kdoc/AtTags.txt +++ b/compiler/testData/psi/kdoc/AtTags.txt @@ -6,12 +6,13 @@ JetFile: AtTags.kt PsiWhiteSpace('\n ') PsiElement(KDOC_LEADING_ASTERISK)('*') PsiElement(KDOC_TEXT)(' ') - PsiElement(KDOC_TAG_NAME)('@tag') - PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' text @notATag') - PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' @') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@tag') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' text @notATag') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' @') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/Markdown.kt b/compiler/testData/psi/kdoc/Markdown.kt index 8811d83ea2e..d605c5755e9 100644 --- a/compiler/testData/psi/kdoc/Markdown.kt +++ b/compiler/testData/psi/kdoc/Markdown.kt @@ -1,4 +1,6 @@ /** - * [[WikiLink]] - * Just \[[ and \]] + * [WikiLink] + * \[NotALink] + * [[DoubleQuotedLink]] + * Just \[ and \] */ \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/Markdown.txt b/compiler/testData/psi/kdoc/Markdown.txt index c98b39a27d5..b71356bf1eb 100644 --- a/compiler/testData/psi/kdoc/Markdown.txt +++ b/compiler/testData/psi/kdoc/Markdown.txt @@ -6,15 +6,24 @@ JetFile: Markdown.kt PsiWhiteSpace('\n ') PsiElement(KDOC_LEADING_ASTERISK)('*') PsiElement(KDOC_TEXT)(' ') - PsiElement(KDOC_WIKI_LINK_OPEN)('[[') - PsiElement(KDOC_TEXT)('WikiLink') - PsiElement(KDOC_WIKI_LINK_CLOSE)(']]') + KDOC_LINK + PsiElement(KDOC_MARKDOWN_LINK)('[WikiLink]') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + PsiElement(KDOC_MARKDOWN_ESCAPED_CHAR)('\[') + PsiElement(KDOC_TEXT)('NotALink]') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' [') + KDOC_LINK + PsiElement(KDOC_MARKDOWN_LINK)('[DoubleQuotedLink]') + PsiElement(KDOC_TEXT)(']') PsiWhiteSpace('\n ') PsiElement(KDOC_LEADING_ASTERISK)('*') PsiElement(KDOC_TEXT)(' Just ') PsiElement(KDOC_MARKDOWN_ESCAPED_CHAR)('\[') - PsiElement(KDOC_TEXT)('[ and ') + PsiElement(KDOC_TEXT)(' and ') PsiElement(KDOC_MARKDOWN_ESCAPED_CHAR)('\]') - PsiElement(KDOC_TEXT)(']') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/ParamTag.kt b/compiler/testData/psi/kdoc/ParamTag.kt new file mode 100644 index 00000000000..dd846afe8eb --- /dev/null +++ b/compiler/testData/psi/kdoc/ParamTag.kt @@ -0,0 +1,3 @@ +/** + * @param a The description of a. + */ diff --git a/compiler/testData/psi/kdoc/ParamTag.txt b/compiler/testData/psi/kdoc/ParamTag.txt new file mode 100644 index 00000000000..7460ebd83b3 --- /dev/null +++ b/compiler/testData/psi/kdoc/ParamTag.txt @@ -0,0 +1,16 @@ +JetFile: ParamTag.kt + PACKAGE_DIRECTIVE + + KDoc + PsiElement(KDOC_START)('/**') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@param') + PsiWhiteSpace(' ') + KDOC_LINK + PsiElement(KDOC_TEXT_OR_LINK)('a') + 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/ReturnWithBrackets.kt b/compiler/testData/psi/kdoc/ReturnWithBrackets.kt new file mode 100644 index 00000000000..a572ce64190 --- /dev/null +++ b/compiler/testData/psi/kdoc/ReturnWithBrackets.kt @@ -0,0 +1,4 @@ +/** + * @return This is not a reference + * @return[x] This is a reference + */ diff --git a/compiler/testData/psi/kdoc/ReturnWithBrackets.txt b/compiler/testData/psi/kdoc/ReturnWithBrackets.txt new file mode 100644 index 00000000000..bf36f34fce1 --- /dev/null +++ b/compiler/testData/psi/kdoc/ReturnWithBrackets.txt @@ -0,0 +1,23 @@ +JetFile: ReturnWithBrackets.kt + PACKAGE_DIRECTIVE + + KDoc + PsiElement(KDOC_START)('/**') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@return') + PsiWhiteSpace(' ') + PsiElement(KDOC_TEXT_OR_LINK)('This') + PsiElement(KDOC_TEXT)(' is not a reference') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@return') + KDOC_LINK + PsiElement(KDOC_MARKDOWN_LINK)('[x]') + PsiElement(KDOC_TEXT)(' This is a reference') + PsiWhiteSpace('\n ') + PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/TwoTags.kt b/compiler/testData/psi/kdoc/TwoTags.kt new file mode 100644 index 00000000000..8897323bc5e --- /dev/null +++ b/compiler/testData/psi/kdoc/TwoTags.kt @@ -0,0 +1,4 @@ +/** + * @author Dmitry Jemerov + * @since M12 + */ \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/TwoTags.txt b/compiler/testData/psi/kdoc/TwoTags.txt new file mode 100644 index 00000000000..ae899544752 --- /dev/null +++ b/compiler/testData/psi/kdoc/TwoTags.txt @@ -0,0 +1,22 @@ +JetFile: TwoTags.kt + PACKAGE_DIRECTIVE + + KDoc + PsiElement(KDOC_START)('/**') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@author') + PsiWhiteSpace(' ') + PsiElement(KDOC_TEXT_OR_LINK)('Dmitry') + PsiElement(KDOC_TEXT)(' Jemerov') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@since') + PsiWhiteSpace(' ') + PsiElement(KDOC_TEXT_OR_LINK)('M12') + PsiWhiteSpace('\n ') + PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java index 3ea708f19d1..d3e3babc9c4 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java @@ -1085,6 +1085,18 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { doParsingTest(fileName); } + @TestMetadata("ParamTag.kt") + public void testParamTag() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/ParamTag.kt"); + doParsingTest(fileName); + } + + @TestMetadata("ReturnWithBrackets.kt") + public void testReturnWithBrackets() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/ReturnWithBrackets.kt"); + doParsingTest(fileName); + } + @TestMetadata("Simple.kt") public void testSimple() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/Simple.kt"); @@ -1096,6 +1108,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/TextRightAfterLeadAsterisks.kt"); doParsingTest(fileName); } + + @TestMetadata("TwoTags.kt") + public void testTwoTags() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/TwoTags.kt"); + doParsingTest(fileName); + } } @TestMetadata("compiler/testData/psi/platformTypesRecovery") diff --git a/idea/src/org/jetbrains/kotlin/idea/JetPairMatcher.java b/idea/src/org/jetbrains/kotlin/idea/JetPairMatcher.java index 266c33db5ff..0e9b443c246 100644 --- a/idea/src/org/jetbrains/kotlin/idea/JetPairMatcher.java +++ b/idea/src/org/jetbrains/kotlin/idea/JetPairMatcher.java @@ -22,7 +22,6 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; import org.jetbrains.kotlin.lexer.JetTokens; public class JetPairMatcher implements PairedBraceMatcher { @@ -31,7 +30,6 @@ public class JetPairMatcher implements PairedBraceMatcher { new BracePair(JetTokens.LONG_TEMPLATE_ENTRY_START, JetTokens.LONG_TEMPLATE_ENTRY_END, false), new BracePair(JetTokens.LBRACE, JetTokens.RBRACE, true), new BracePair(JetTokens.LBRACKET, JetTokens.RBRACKET, false), - new BracePair(KDocTokens.WIKI_LINK_OPEN, KDocTokens.WIKI_LINK_CLOSE, false) }; @Override @@ -46,8 +44,6 @@ public class JetPairMatcher implements PairedBraceMatcher { return false; } - if (lbraceType == KDocTokens.WIKI_LINK_OPEN) return false; - return JetTokens.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(contextType) || contextType == JetTokens.SEMICOLON || contextType == JetTokens.COMMA