From f3763bc2b5fb9fdb35d47f94a5fc447f54cbd67a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 19 Jan 2015 20:54:05 +0100 Subject: [PATCH 1/5] 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 From c3a496b9a2903627ae33bdfe573ac4f29311c773 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Jan 2015 12:29:44 +0100 Subject: [PATCH 2/5] introduce the concept of sections --- .../kotlin/kdoc/parser/KDocElementTypes.java | 2 + .../kotlin/kdoc/parser/KDocKnownTag.java | 24 +++++++---- .../kotlin/kdoc/parser/KDocParser.java | 25 +++++++++-- .../kotlin/kdoc/psi/impl/KDocSection.java | 32 ++++++++++++++ compiler/testData/psi/CommentsBinding.txt | 14 +++--- .../psi/DocCommentAfterFileAnnotations.txt | 5 ++- .../psi/DocCommentForFirstDeclaration.txt | 5 ++- .../psi/DocCommentOnPackageDirectiveLine.txt | 3 +- compiler/testData/psi/DocCommentsBinding.txt | 41 +++++++++++------- compiler/testData/psi/EOLsInComments.txt | 5 ++- compiler/testData/psi/NestedComments.txt | 12 ++++-- .../psi/examples/array/MutableArray.txt | 3 +- compiler/testData/psi/kdoc/AtTags.txt | 19 ++++---- .../psi/kdoc/DocCommentAtBeginningOfFile1.txt | 4 +- .../psi/kdoc/DocCommentAtBeginningOfFile2.txt | 3 +- .../psi/kdoc/DocCommentAtBeginningOfFile3.txt | 3 +- .../psi/kdoc/DocCommentAtBeginningOfFile4.txt | 7 +-- .../psi/kdoc/EndOnLeadingAsterisks.txt | 2 + .../testData/psi/kdoc/EndRightAfterText.txt | 3 +- compiler/testData/psi/kdoc/Incomplete.txt | 3 +- compiler/testData/psi/kdoc/Markdown.txt | 43 ++++++++++--------- compiler/testData/psi/kdoc/ParamTag.txt | 17 ++++---- .../testData/psi/kdoc/ReturnWithBrackets.txt | 31 ++++++------- compiler/testData/psi/kdoc/Sections.kt | 6 +++ compiler/testData/psi/kdoc/Sections.txt | 38 ++++++++++++++++ compiler/testData/psi/kdoc/Simple.txt | 35 +++++++-------- .../psi/kdoc/TextRightAfterLeadAsterisks.txt | 5 ++- compiler/testData/psi/kdoc/TwoTags.txt | 29 +++++++------ .../parsing/JetParsingTestGenerated.java | 6 +++ 29 files changed, 288 insertions(+), 137 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java create mode 100644 compiler/testData/psi/kdoc/Sections.kt create mode 100644 compiler/testData/psi/kdoc/Sections.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java index bf3ebd95014..6ff530e4cf4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementTypes.java @@ -17,9 +17,11 @@ package org.jetbrains.kotlin.kdoc.parser; import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink; +import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection; 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); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java index 9a2acf563e9..f7bb5a6b4d0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocKnownTag.java @@ -17,24 +17,32 @@ package org.jetbrains.kotlin.kdoc.parser; public enum KDocKnownTag { - AUTHOR(false), - THROWS(true), - EXCEPTION(true), - PARAM(true), - RETURN(false), - SEE(false), - SINCE(false); + AUTHOR(false, false), + THROWS(true, false), + EXCEPTION(true, false), + PARAM(true, false), + RETURN(false, false), + SEE(false, false), + SINCE(false, false), + CONSTRUCTOR(false, true), + PROPERTY(true, true); private final boolean takesReference; + private final boolean startsSection; - KDocKnownTag(boolean takesReference) { + KDocKnownTag(boolean takesReference, boolean startsSection) { this.takesReference = takesReference; + this.startsSection = startsSection; } public boolean isReferenceRequired() { return takesReference; } + public boolean isSectionStart() { + return startsSection; + } + public static KDocKnownTag findByTagName(String tagName) { if (tagName.startsWith("@")) { try { 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 f8fcaa5a5b3..288346f243b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocParser.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocParser.java @@ -28,30 +28,48 @@ public class KDocParser implements PsiParser { @NotNull public ASTNode parse(IElementType root, PsiBuilder builder) { PsiBuilder.Marker rootMarker = builder.mark(); + if (builder.getTokenType() == KDocTokens.START) { + builder.advanceLexer(); + } + PsiBuilder.Marker currentSectionMarker = builder.mark(); // todo: parse KDoc tags, markdown, etc... while (!builder.eof()) { if (builder.getTokenType() == KDocTokens.TAG_NAME) { - parseTag(builder); + 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); + currentSectionMarker = null; + } + builder.advanceLexer(); + } else { builder.advanceLexer(); } } + if (currentSectionMarker != null) { + currentSectionMarker.done(KDocElementTypes.KDOC_SECTION); + } rootMarker.done(root); return builder.getTreeBuilt(); } - private static void parseTag(PsiBuilder builder) { - PsiBuilder.Marker tagStart = builder.mark(); + private static PsiBuilder.Marker parseTag(PsiBuilder builder, PsiBuilder.Marker currentSectionMarker) { String tagName = builder.getTokenText(); KDocKnownTag knownTag = KDocKnownTag.findByTagName(tagName); + if (knownTag != null && knownTag.isSectionStart()) { + currentSectionMarker.done(KDocElementTypes.KDOC_SECTION); + currentSectionMarker = builder.mark(); + } + PsiBuilder.Marker tagStart = builder.mark(); builder.advanceLexer(); if (knownTag != null && knownTag.isReferenceRequired() && builder.getTokenType() == KDocTokens.TEXT_OR_LINK) { @@ -71,6 +89,7 @@ public class KDocParser implements PsiParser { } } tagStart.done(KDocElementTypes.KDOC_TAG); + return currentSectionMarker; } private static boolean isAtEndOfTag(PsiBuilder builder) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java new file mode 100644 index 00000000000..23d1e53fcc8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java @@ -0,0 +1,32 @@ +/* + * 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; + +/** + * The part of a doc comment which describes a single class, method or property + * produced by the element being documented. For example, the doc comment of a class + * can have sections for the class itself, its primary constructor and each of the + * properties defined in the primary constructor. + */ +public class KDocSection extends KDocElementImpl { + public KDocSection(@NotNull ASTNode node) { + super(node); + } +} diff --git a/compiler/testData/psi/CommentsBinding.txt b/compiler/testData/psi/CommentsBinding.txt index 33abacdbe8e..1cf194fbc68 100644 --- a/compiler/testData/psi/CommentsBinding.txt +++ b/compiler/testData/psi/CommentsBinding.txt @@ -64,8 +64,9 @@ JetFile: CommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for A') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for A') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') @@ -128,7 +129,8 @@ JetFile: CommentsBinding.kt PROPERTY KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' v2 doc comment ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' v2 doc comment ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') PsiElement(val)('val') @@ -356,7 +358,8 @@ JetFile: CommentsBinding.kt ENUM_ENTRY KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' This is B ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' This is B ') PsiElement(KDOC_END)('*/') PsiWhiteSpace(' ') OBJECT_DECLARATION_NAME @@ -371,7 +374,8 @@ JetFile: CommentsBinding.kt ENUM_ENTRY KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' This is X ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' This is X ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') OBJECT_DECLARATION_NAME diff --git a/compiler/testData/psi/DocCommentAfterFileAnnotations.txt b/compiler/testData/psi/DocCommentAfterFileAnnotations.txt index b5cc56c9605..55293c01796 100644 --- a/compiler/testData/psi/DocCommentAfterFileAnnotations.txt +++ b/compiler/testData/psi/DocCommentAfterFileAnnotations.txt @@ -18,8 +18,9 @@ JetFile: DocCommentAfterFileAnnotations.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') diff --git a/compiler/testData/psi/DocCommentForFirstDeclaration.txt b/compiler/testData/psi/DocCommentForFirstDeclaration.txt index 58db3ebfed5..847f6418ea0 100644 --- a/compiler/testData/psi/DocCommentForFirstDeclaration.txt +++ b/compiler/testData/psi/DocCommentForFirstDeclaration.txt @@ -5,8 +5,9 @@ JetFile: DocCommentForFirstDeclaration.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') diff --git a/compiler/testData/psi/DocCommentOnPackageDirectiveLine.txt b/compiler/testData/psi/DocCommentOnPackageDirectiveLine.txt index a21d9b42285..c82fa97d5f3 100644 --- a/compiler/testData/psi/DocCommentOnPackageDirectiveLine.txt +++ b/compiler/testData/psi/DocCommentOnPackageDirectiveLine.txt @@ -12,7 +12,8 @@ JetFile: DocCommentOnPackageDirectiveLine.kt FUN KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' some ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' some ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') PsiElement(fun)('fun') diff --git a/compiler/testData/psi/DocCommentsBinding.txt b/compiler/testData/psi/DocCommentsBinding.txt index ae98d9eb4a9..12f113f54b4 100644 --- a/compiler/testData/psi/DocCommentsBinding.txt +++ b/compiler/testData/psi/DocCommentsBinding.txt @@ -5,8 +5,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for A') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for A') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') @@ -22,8 +23,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for val-parameter') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for val-parameter') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') @@ -47,8 +49,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for function') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for function') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') @@ -66,8 +69,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for local function') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for local function') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') @@ -87,8 +91,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for local class') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for local class') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') @@ -102,8 +107,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for property') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for property') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') @@ -120,7 +126,8 @@ JetFile: DocCommentsBinding.kt PROPERTY_ACCESSOR KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' Doc comment for getter ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' Doc comment for getter ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') PsiElement(get)('get') @@ -135,7 +142,8 @@ JetFile: DocCommentsBinding.kt PROPERTY_ACCESSOR KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' Doc comment for setter ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' Doc comment for setter ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n ') PsiElement(set)('set') @@ -155,8 +163,9 @@ JetFile: DocCommentsBinding.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' Doc comment for B') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' Doc comment for B') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') diff --git a/compiler/testData/psi/EOLsInComments.txt b/compiler/testData/psi/EOLsInComments.txt index 8ae92f0ef03..4a71517c269 100644 --- a/compiler/testData/psi/EOLsInComments.txt +++ b/compiler/testData/psi/EOLsInComments.txt @@ -27,7 +27,8 @@ JetFile: EOLsInComments.kt PsiWhiteSpace('\n ') KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' ') PsiElement(KDOC_END)('*/') PREFIX_EXPRESSION OPERATION_REFERENCE @@ -78,6 +79,8 @@ JetFile: EOLsInComments.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') + KDOC_SECTION + PsiElement(KDOC_END)('*/') PsiWhiteSpace(' ') OPERATION_REFERENCE diff --git a/compiler/testData/psi/NestedComments.txt b/compiler/testData/psi/NestedComments.txt index 95052f017b2..7bc702a1edb 100644 --- a/compiler/testData/psi/NestedComments.txt +++ b/compiler/testData/psi/NestedComments.txt @@ -34,6 +34,8 @@ JetFile: NestedComments.kt PsiWhiteSpace('\n') KDoc PsiElement(KDOC_START)('/**') + KDOC_SECTION + PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') REFERENCE_EXPRESSION @@ -41,7 +43,8 @@ JetFile: NestedComments.kt PsiWhiteSpace('\n') KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' /***/') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' /***/') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n') REFERENCE_EXPRESSION @@ -49,9 +52,10 @@ JetFile: NestedComments.kt PsiWhiteSpace('\n') KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' /**') - PsiWhiteSpace('\n\n') - PsiElement(KDOC_TEXT)('*/') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' /**') + PsiWhiteSpace('\n\n') + PsiElement(KDOC_TEXT)('*/') PsiElement(KDOC_END)('***/') PsiWhiteSpace('\n') REFERENCE_EXPRESSION diff --git a/compiler/testData/psi/examples/array/MutableArray.txt b/compiler/testData/psi/examples/array/MutableArray.txt index 928e7874a03..086fdc1bbbf 100644 --- a/compiler/testData/psi/examples/array/MutableArray.txt +++ b/compiler/testData/psi/examples/array/MutableArray.txt @@ -5,7 +5,8 @@ JetFile: MutableArray.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_TEXT)('These declarations are "shallow" in the sense that they are not really compiled, only the type-checker uses them') + KDOC_SECTION + PsiElement(KDOC_TEXT)('These declarations are "shallow" in the sense that they are not really compiled, only the type-checker uses them') PsiWhiteSpace('\n') PsiElement(KDOC_END)('*/') PsiWhiteSpace('\n\n') diff --git a/compiler/testData/psi/kdoc/AtTags.txt b/compiler/testData/psi/kdoc/AtTags.txt index 88fb41a42d6..ec8e2af4423 100644 --- a/compiler/testData/psi/kdoc/AtTags.txt +++ b/compiler/testData/psi/kdoc/AtTags.txt @@ -4,15 +4,16 @@ JetFile: AtTags.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' ') - KDOC_TAG - PsiElement(KDOC_TAG_NAME)('@tag') - PsiWhiteSpace('\n ') + KDOC_SECTION PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' text @notATag') - PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' @') + 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/DocCommentAtBeginningOfFile1.txt b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile1.txt index cf6ca9c30f0..80f2a9b0e73 100644 --- a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile1.txt +++ b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile1.txt @@ -2,4 +2,6 @@ JetFile: DocCommentAtBeginningOfFile1.kt PACKAGE_DIRECTIVE KDoc - PsiElement(KDOC_START)('/**') \ No newline at end of file + PsiElement(KDOC_START)('/**') + KDOC_SECTION + \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile2.txt b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile2.txt index c497cb3aa3b..3bf014c4e16 100644 --- a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile2.txt +++ b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile2.txt @@ -4,4 +4,5 @@ JetFile: DocCommentAtBeginningOfFile2.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n') - PsiElement(KDOC_TEXT)('/**') \ No newline at end of file + KDOC_SECTION + PsiElement(KDOC_TEXT)('/**') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile3.txt b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile3.txt index a0b7c9e63db..048dd536e33 100644 --- a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile3.txt +++ b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile3.txt @@ -4,4 +4,5 @@ JetFile: DocCommentAtBeginningOfFile3.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n\n') - PsiElement(KDOC_TEXT)('fooo') \ No newline at end of file + KDOC_SECTION + PsiElement(KDOC_TEXT)('fooo') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile4.txt b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile4.txt index d882da21f3a..78297346043 100644 --- a/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile4.txt +++ b/compiler/testData/psi/kdoc/DocCommentAtBeginningOfFile4.txt @@ -4,6 +4,7 @@ JetFile: DocCommentAtBeginningOfFile4.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n\n') - PsiElement(KDOC_TEXT)('/**foo*/') - PsiWhiteSpace('\n\n') - PsiElement(KDOC_TEXT)('asdfas') \ No newline at end of file + KDOC_SECTION + PsiElement(KDOC_TEXT)('/**foo*/') + PsiWhiteSpace('\n\n') + PsiElement(KDOC_TEXT)('asdfas') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/EndOnLeadingAsterisks.txt b/compiler/testData/psi/kdoc/EndOnLeadingAsterisks.txt index ac62c23340c..f46b84cfa81 100644 --- a/compiler/testData/psi/kdoc/EndOnLeadingAsterisks.txt +++ b/compiler/testData/psi/kdoc/EndOnLeadingAsterisks.txt @@ -4,4 +4,6 @@ JetFile: EndOnLeadingAsterisks.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') + KDOC_SECTION + PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/EndRightAfterText.txt b/compiler/testData/psi/kdoc/EndRightAfterText.txt index 15dca239106..a3b94b5dfb6 100644 --- a/compiler/testData/psi/kdoc/EndRightAfterText.txt +++ b/compiler/testData/psi/kdoc/EndRightAfterText.txt @@ -3,5 +3,6 @@ JetFile: EndRightAfterText.kt KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)('text') + KDOC_SECTION + PsiElement(KDOC_TEXT)('text') PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/Incomplete.txt b/compiler/testData/psi/kdoc/Incomplete.txt index b16a862297e..78dfb42b89b 100644 --- a/compiler/testData/psi/kdoc/Incomplete.txt +++ b/compiler/testData/psi/kdoc/Incomplete.txt @@ -4,4 +4,5 @@ JetFile: Incomplete.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_TEXT)('contents') \ No newline at end of file + KDOC_SECTION + PsiElement(KDOC_TEXT)('contents') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/Markdown.txt b/compiler/testData/psi/kdoc/Markdown.txt index b71356bf1eb..3dc99a1e0f3 100644 --- a/compiler/testData/psi/kdoc/Markdown.txt +++ b/compiler/testData/psi/kdoc/Markdown.txt @@ -4,26 +4,27 @@ JetFile: Markdown.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' ') - 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_MARKDOWN_ESCAPED_CHAR)('\]') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + 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_MARKDOWN_ESCAPED_CHAR)('\]') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/ParamTag.txt b/compiler/testData/psi/kdoc/ParamTag.txt index 7460ebd83b3..9c59b997775 100644 --- a/compiler/testData/psi/kdoc/ParamTag.txt +++ b/compiler/testData/psi/kdoc/ParamTag.txt @@ -4,13 +4,14 @@ JetFile: ParamTag.kt 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.') + KDOC_SECTION + 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.txt b/compiler/testData/psi/kdoc/ReturnWithBrackets.txt index bf36f34fce1..554d1a069e9 100644 --- a/compiler/testData/psi/kdoc/ReturnWithBrackets.txt +++ b/compiler/testData/psi/kdoc/ReturnWithBrackets.txt @@ -4,20 +4,21 @@ JetFile: ReturnWithBrackets.kt 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') + KDOC_SECTION + 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/Sections.kt b/compiler/testData/psi/kdoc/Sections.kt new file mode 100644 index 00000000000..3f2652136f2 --- /dev/null +++ b/compiler/testData/psi/kdoc/Sections.kt @@ -0,0 +1,6 @@ +/** + * This is the doc comment for a class. + * @param T a type parameter. + * @constructor This is the doc comment for the primary constructor. + * @param a a constructor parameter. + */ \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/Sections.txt b/compiler/testData/psi/kdoc/Sections.txt new file mode 100644 index 00000000000..30080e32e6c --- /dev/null +++ b/compiler/testData/psi/kdoc/Sections.txt @@ -0,0 +1,38 @@ +JetFile: Sections.kt + PACKAGE_DIRECTIVE + + KDoc + PsiElement(KDOC_START)('/**') + PsiWhiteSpace('\n ') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' This is the doc comment for a class.') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_TAG + PsiElement(KDOC_TAG_NAME)('@param') + PsiWhiteSpace(' ') + KDOC_LINK + PsiElement(KDOC_TEXT_OR_LINK)('T') + PsiElement(KDOC_TEXT)(' a type parameter.') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' ') + KDOC_SECTION + 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.') + 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)(' a constructor parameter.') + PsiWhiteSpace('\n ') + PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/Simple.txt b/compiler/testData/psi/kdoc/Simple.txt index 1661f7c3fb5..a7be8769ebe 100644 --- a/compiler/testData/psi/kdoc/Simple.txt +++ b/compiler/testData/psi/kdoc/Simple.txt @@ -3,21 +3,22 @@ JetFile: Simple.kt KDoc PsiElement(KDOC_START)('/**') - PsiElement(KDOC_TEXT)(' line 0') - PsiWhiteSpace('\n ') - PsiElement(KDOC_TEXT)('line 1 //') - PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('**') - PsiElement(KDOC_TEXT)(' line 2 /*') - PsiWhiteSpace('\n ') - PsiElement(KDOC_TEXT)('line 3 /**') - PsiWhiteSpace('\n') - PsiElement(KDOC_LEADING_ASTERISK)('*') - PsiElement(KDOC_TEXT)(' line * 4') - PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('***') - PsiElement(KDOC_TEXT)(' line */ 5') - PsiWhiteSpace('\n ') - PsiElement(KDOC_LEADING_ASTERISK)('**') - PsiElement(KDOC_TEXT)(' line 6 ') + KDOC_SECTION + PsiElement(KDOC_TEXT)(' line 0') + PsiWhiteSpace('\n ') + PsiElement(KDOC_TEXT)('line 1 //') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('**') + PsiElement(KDOC_TEXT)(' line 2 /*') + PsiWhiteSpace('\n ') + PsiElement(KDOC_TEXT)('line 3 /**') + PsiWhiteSpace('\n') + PsiElement(KDOC_LEADING_ASTERISK)('*') + PsiElement(KDOC_TEXT)(' line * 4') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('***') + PsiElement(KDOC_TEXT)(' line */ 5') + PsiWhiteSpace('\n ') + PsiElement(KDOC_LEADING_ASTERISK)('**') + PsiElement(KDOC_TEXT)(' line 6 ') PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/TextRightAfterLeadAsterisks.txt b/compiler/testData/psi/kdoc/TextRightAfterLeadAsterisks.txt index 1f8ac66cb20..96ff061f008 100644 --- a/compiler/testData/psi/kdoc/TextRightAfterLeadAsterisks.txt +++ b/compiler/testData/psi/kdoc/TextRightAfterLeadAsterisks.txt @@ -4,7 +4,8 @@ JetFile: TextRightAfterLeadAsterisks.kt KDoc PsiElement(KDOC_START)('/**') PsiWhiteSpace('\n') - PsiElement(KDOC_LEADING_ASTERISK)('**') - PsiElement(KDOC_TEXT)('test') + KDOC_SECTION + PsiElement(KDOC_LEADING_ASTERISK)('**') + PsiElement(KDOC_TEXT)('test') PsiWhiteSpace('\n ') PsiElement(KDOC_END)('*/') \ No newline at end of file diff --git a/compiler/testData/psi/kdoc/TwoTags.txt b/compiler/testData/psi/kdoc/TwoTags.txt index ae899544752..22a99dfe0b2 100644 --- a/compiler/testData/psi/kdoc/TwoTags.txt +++ b/compiler/testData/psi/kdoc/TwoTags.txt @@ -4,19 +4,20 @@ JetFile: TwoTags.kt 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') + KDOC_SECTION + 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 d3e3babc9c4..2e8dd95174e 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java @@ -1097,6 +1097,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { doParsingTest(fileName); } + @TestMetadata("Sections.kt") + public void testSections() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/Sections.kt"); + doParsingTest(fileName); + } + @TestMetadata("Simple.kt") public void testSimple() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/Simple.kt"); From 100b8c2c4da825307baa27bd1aa34800eae2c013 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Jan 2015 16:39:59 +0100 Subject: [PATCH 3/5] Fix tests according to new PSI structure; move doc comment text calculation from JetQuickDocumentationProvider to KDocTag.getContent() --- .../kotlin/kdoc/lexer/KDocTokens.java | 2 +- .../jetbrains/kotlin/kdoc/psi/api/KDoc.java | 2 + .../kotlin/kdoc/psi/impl/KDocImpl.java | 6 ++ .../kotlin/kdoc/psi/impl/KDocSection.java | 2 +- .../kotlin/kdoc/psi/impl/KDocTag.java | 57 +++++++++++++++++++ .../parsing/JetCodeConformanceTest.java | 1 + .../idea/JetQuickDocumentationProvider.java | 31 +--------- .../KotlinWordSelectionFilter.kt | 3 +- .../kotlin/idea/formatter/JetBlock.java | 5 +- .../editor/quickDoc/MethodFromStdLib.kt | 2 +- .../OnClassDeclarationWithNoPackage.kt | 2 +- .../quickDoc/TopLevelMethodFromJava.java | 2 +- 12 files changed, 78 insertions(+), 37 deletions(-) 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 4eaf77f4b49..f8d918d4b45 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java @@ -57,7 +57,7 @@ public interface KDocTokens { /** * 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). + * 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"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.java index cf902a2b358..bd1a86f5384 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/api/KDoc.java @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.kdoc.psi.api; import com.intellij.psi.PsiComment; +import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection; // Don't implement JetElement (or it will be treated as statement) public interface KDoc extends PsiComment { + KDocSection getDefaultSection(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.java index b1b47a0eae9..4db5d18e0c3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocImpl.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.kdoc.psi.impl; import com.intellij.lang.Language; import com.intellij.psi.impl.source.tree.LazyParseablePsiElement; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.JetLanguage; import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; @@ -45,4 +46,9 @@ public class KDocImpl extends LazyParseablePsiElement implements KDoc { public IElementType getTokenType() { return JetTokens.DOC_COMMENT; } + + @Override + public KDocSection getDefaultSection() { + return PsiTreeUtil.getChildOfType(this, KDocSection.class); + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java index 23d1e53fcc8..292d9524577 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocSection.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull; * can have sections for the class itself, its primary constructor and each of the * properties defined in the primary constructor. */ -public class KDocSection extends KDocElementImpl { +public class KDocSection extends KDocTag { public KDocSection(@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 index 59b2fc1403f..5e24ac6015d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java @@ -17,11 +17,68 @@ package org.jetbrains.kotlin.kdoc.psi.impl; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.TokenType; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; +import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes; public class KDocTag extends KDocElementImpl { public KDocTag(@NotNull ASTNode node) { super(node); } + public String getContent() { + StringBuilder builder = new StringBuilder(); + + boolean contentStarted = false; + boolean afterAsterisk = false; + boolean startsWithTagName = false; + + ASTNode[] children = getNode().getChildren(null); + for (int i = 0; i < children.length; i++) { + ASTNode node = children[i]; + IElementType type = node.getElementType(); + if (i == 0 && type == KDocTokens.TAG_NAME) { + startsWithTagName = true; + } + if (KDocTokens.CONTENT_TOKENS.contains(type) || type == KDocElementTypes.KDOC_LINK) { + contentStarted = true; + builder.append(afterAsterisk ? StringUtil.trimLeading(node.getText()) : node.getText()); + afterAsterisk = false; + } + + if (type == KDocTokens.LEADING_ASTERISK || type == KDocTokens.START) { + afterAsterisk = true; + } + + if (type == TokenType.WHITE_SPACE) { + if (i == 1 && startsWithTagName) { + builder.append(node.getText()); + } + else if (contentStarted) { + builder.append(StringUtil.repeat("\n", StringUtil.countNewLines(node.getText()))); + } + } + + if (type == KDocElementTypes.KDOC_TAG) { + break; + } + } + + return builder.toString(); + } + + public String getContentWithTags() { + StringBuilder content = new StringBuilder(getContent()); + KDocTag[] subTags = PsiTreeUtil.getChildrenOfType(this, KDocTag.class); + if (subTags != null) { + for (KDocTag tag : subTags) { + content.append(tag.getContentWithTags()).append("\n"); + } + } + return content.toString(); + } } diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/JetCodeConformanceTest.java b/compiler/tests/org/jetbrains/kotlin/parsing/JetCodeConformanceTest.java index 2f5de3cd832..10f0e887c81 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/JetCodeConformanceTest.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/JetCodeConformanceTest.java @@ -46,6 +46,7 @@ public class JetCodeConformanceTest extends TestCase { new File("docs"), new File("ideaSDK"), new File("libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build/tmp"), + new File("compiler/testData/psi/kdoc"), new File("compiler/tests/org/jetbrains/kotlin/parsing/JetCodeConformanceTest.java")); public static final Pattern AUTHOR_JAVADOC_PATTERN = Pattern.compile("/\\*.+@author.+\\*/", Pattern.DOTALL); diff --git a/idea/src/org/jetbrains/kotlin/idea/JetQuickDocumentationProvider.java b/idea/src/org/jetbrains/kotlin/idea/JetQuickDocumentationProvider.java index 00631b51c39..a8ad059cc91 100644 --- a/idea/src/org/jetbrains/kotlin/idea/JetQuickDocumentationProvider.java +++ b/idea/src/org/jetbrains/kotlin/idea/JetQuickDocumentationProvider.java @@ -22,13 +22,11 @@ import com.intellij.lang.java.JavaDocumentationProvider; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.asJava.KotlinLightMethod; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; -import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; import org.jetbrains.kotlin.kdoc.psi.api.KDoc; import org.jetbrains.kotlin.psi.JetDeclaration; import org.jetbrains.kotlin.psi.JetPackageDirective; @@ -117,36 +115,9 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider return null; } - private static String getKDocContent(@NotNull KDoc kDoc) { - StringBuilder builder = new StringBuilder(); - - boolean contentStarted = false; - boolean afterAsterisk = false; - - for (PsiElement element : kDoc.getChildren()) { - IElementType type = element.getNode().getElementType(); - - if (KDocTokens.CONTENT_TOKENS.contains(type)) { - contentStarted = true; - builder.append(afterAsterisk ? StringUtil.trimLeading(element.getText()) : element.getText()); - afterAsterisk = false; - } - - if (type == KDocTokens.LEADING_ASTERISK || type == KDocTokens.START) { - afterAsterisk = true; - } - - if (contentStarted && element instanceof PsiWhiteSpace) { - builder.append(StringUtil.repeat("\n", StringUtil.countNewLines(element.getText()))); - } - } - - return builder.toString(); - } - private static String kDocToHtml(@NotNull KDoc comment) { // TODO: Parse and show markdown comments as html - String content = getKDocContent(comment); + String content = comment.getDefaultSection().getContentWithTags(); String htmlContent = StringUtil.replace(content, "\n", "
") .replaceAll("(@param)\\s+(\\w+)", "@param - $2") .replaceAll("(@\\w+)", "$1"); diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt b/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt index e342863544c..b037e6ce543 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/editor/wordSelection/KotlinWordSelectionFilter.kt @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.JetNodeTypes.* import org.jetbrains.kotlin.psi.JetContainerNode import org.jetbrains.kotlin.idea.JetLanguage +import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes public class KotlinWordSelectionFilter : Condition{ override fun value(e: PsiElement): Boolean { @@ -31,7 +32,7 @@ public class KotlinWordSelectionFilter : Condition{ if (e.getParent().getFirstChild().getNextSibling() == null && e.getParent() !is JetContainerNode) return false // skip nodes with the same range as their parent return when (e.getNode().getElementType()) { - BLOCK, LITERAL_STRING_TEMPLATE_ENTRY -> false + BLOCK, LITERAL_STRING_TEMPLATE_ENTRY, KDocElementTypes.KDOC_SECTION -> false else -> true } } diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/JetBlock.java b/idea/src/org/jetbrains/kotlin/idea/formatter/JetBlock.java index 6d9a544fd1c..8fc01c09af8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/JetBlock.java +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/JetBlock.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.JetLanguage; import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; +import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.JetDeclaration; @@ -65,6 +66,8 @@ public class JetBlock extends AbstractBlock { CLASS_BODY, FUNCTION_LITERAL); + private static final TokenSet KDOC_CONTENT = TokenSet.create(KDocTokens.KDOC, KDocElementTypes.KDOC_SECTION); + // private static final List public JetBlock( @@ -415,7 +418,7 @@ public class JetBlock extends AbstractBlock { .set(Indent.getContinuationWithoutFirstIndent(false)), strategy("KDoc comment indent") - .in(DOC_COMMENT) + .in(KDOC_CONTENT) .forType(KDocTokens.LEADING_ASTERISK, KDocTokens.END) .set(Indent.getSpaceIndent(KDOC_COMMENT_INDENT)), diff --git a/idea/testData/editor/quickDoc/MethodFromStdLib.kt b/idea/testData/editor/quickDoc/MethodFromStdLib.kt index fb877444ad4..eb2bed96877 100644 --- a/idea/testData/editor/quickDoc/MethodFromStdLib.kt +++ b/idea/testData/editor/quickDoc/MethodFromStdLib.kt @@ -2,4 +2,4 @@ fun test() { listOf(1, 2, 4).filter { it > 0 } } -// INFO: inline public fun <T> Iterable<T>.filter(predicate: (T) → Boolean): List<T>

Returns a list containing all elements matching the given *predicate*

+// INFO: inline public fun <T> Iterable<T>.filter(predicate: (T) → Boolean): List<T>

Returns a list containing all elements matching the given *predicate*

diff --git a/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt b/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt index f239fcee906..e85de36f4aa 100644 --- a/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt +++ b/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt @@ -3,4 +3,4 @@ */ class Some -// INFO: internal final class Some

Usefull comment

\ No newline at end of file +// INFO: internal final class Some

Usefull comment

\ No newline at end of file diff --git a/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java b/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java index d7ddf7007fd..fde04a1cd48 100644 --- a/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java +++ b/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java @@ -8,4 +8,4 @@ class Testing { } } -// INFO: internal fun foo(bar: Int): Unit

KDoc foo

\ No newline at end of file +// INFO: internal fun foo(bar: Int): Unit

KDoc foo

\ No newline at end of file From 31f5441f6b189c88372ebdab409f94b4f7486cb7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Jan 2015 16:43:28 +0100 Subject: [PATCH 4/5] code review --- .../jetbrains/kotlin/kdoc/parser/KDocElementType.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java index 70704187ee7..4993d8b2a08 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/parser/KDocElementType.java @@ -18,18 +18,19 @@ package org.jetbrains.kotlin.kdoc.parser; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; 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; + private final Constructor psiFactory; - public KDocElementType(String debugName, Class psiClass) { + public KDocElementType(String debugName, @NotNull Class psiClass) { super(debugName, JetLanguage.INSTANCE); try { - myPsiFactory = psiClass != null ? psiClass.getConstructor(ASTNode.class) : null; + psiFactory = psiClass != null ? psiClass.getConstructor(ASTNode.class) : null; } catch (NoSuchMethodException e) { throw new RuntimeException("Must have a constructor with ASTNode"); } @@ -39,7 +40,7 @@ public class KDocElementType extends IElementType { assert node.getElementType() == this; try { - return myPsiFactory.newInstance(node); + return psiFactory.newInstance(node); } catch (Exception e) { throw new RuntimeException("Error creating psi element for node", e); } From 8217563aac1c66d7b0be8bc40414e7d687885ebc Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Jan 2015 18:06:27 +0100 Subject: [PATCH 5/5] KDocTokens.START can't be the first token of a tag --- .../src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 5e24ac6015d..737a60da377 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/kdoc/psi/impl/KDocTag.java @@ -50,7 +50,7 @@ public class KDocTag extends KDocElementImpl { afterAsterisk = false; } - if (type == KDocTokens.LEADING_ASTERISK || type == KDocTokens.START) { + if (type == KDocTokens.LEADING_ASTERISK) { afterAsterisk = true; }