Doc comments for parameters and property accessors

This commit is contained in:
Valentin Kipyatkov
2014-10-30 18:32:59 +03:00
parent 6915255d2f
commit 2200908367
9 changed files with 258 additions and 31 deletions
@@ -378,9 +378,10 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
return myBuilder.newlineBeforeCurrentToken() || eof();
}
protected static void closeDeclarationWithCommentBinders(@NotNull PsiBuilder.Marker marker, @NotNull IElementType elementType) {
protected static void closeDeclarationWithCommentBinders(@NotNull PsiBuilder.Marker marker, @NotNull IElementType elementType, boolean precedingNonDocComments) {
marker.done(elementType);
marker.setCustomEdgeTokenBinders(PrecedingWhitespacesAndCommentsBinder.INSTANCE$, TrailingWhitespacesAndCommentsBinder.INSTANCE$);
marker.setCustomEdgeTokenBinders(precedingNonDocComments ? PrecedingCommentsBinder.INSTANCE$ : PrecedingDocCommentsBinder.INSTANCE$,
TrailingCommentsBinder.INSTANCE$);
}
protected abstract JetParsing create(SemanticWhitespaceAwarePsiBuilder builder);
@@ -21,7 +21,7 @@ import com.intellij.psi.tree.IElementType
import org.jetbrains.jet.lexer.JetTokens
import com.intellij.openapi.util.text.StringUtil
object PrecedingWhitespacesAndCommentsBinder : WhitespacesAndCommentsBinder {
object PrecedingCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
@@ -52,8 +52,28 @@ object PrecedingWhitespacesAndCommentsBinder : WhitespacesAndCommentsBinder {
}
}
object PrecedingDocCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
for (idx in tokens.indices.reversed()) {
val tokenType = tokens[idx]
when (tokenType) {
JetTokens.DOC_COMMENT -> return idx
JetTokens.WHITE_SPACE -> continue
else -> break
}
}
return tokens.size
}
}
// Binds comments on the same line
object TrailingWhitespacesAndCommentsBinder : WhitespacesAndCommentsBinder {
object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.parsing;
import com.google.common.collect.ImmutableMap;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.WhitespacesAndCommentsBinder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
@@ -960,13 +959,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected());
if (declType != null) {
decl.done(declType);
// we do not attach preceding comments to local variables because they are likely commenting a few statements below
WhitespacesAndCommentsBinder leftBinder = declType == JetNodeTypes.PROPERTY || declType == JetNodeTypes.MULTI_VARIABLE_DECLARATION
? null
: PrecedingWhitespacesAndCommentsBinder.INSTANCE$;
decl.setCustomEdgeTokenBinders(leftBinder,
TrailingWhitespacesAndCommentsBinder.INSTANCE$);
// we do not attach preceding comments (non-doc) to local variables because they are likely commenting a few statements below
closeDeclarationWithCommentBinders(decl, declType, declType != JetNodeTypes.PROPERTY && declType != JetNodeTypes.MULTI_VARIABLE_DECLARATION);
return true;
}
else {
@@ -211,7 +211,7 @@ public class JetParsing extends AbstractJetParsing {
packageDirective = mark();
packageDirective.done(PACKAGE_DIRECTIVE);
// this is necessary to allow comments at the start of the file to be bound to the first declaration:
packageDirective.setCustomEdgeTokenBinders(PrecedingWhitespacesAndCommentsBinder.INSTANCE$, null);
packageDirective.setCustomEdgeTokenBinders(PrecedingCommentsBinder.INSTANCE$, null);
}
parseImportDirectives();
@@ -318,7 +318,7 @@ public class JetParsing extends AbstractJetParsing {
}
consumeIf(SEMICOLON);
importDirective.done(IMPORT_DIRECTIVE);
importDirective.setCustomEdgeTokenBinders(null, TrailingWhitespacesAndCommentsBinder.INSTANCE$);
importDirective.setCustomEdgeTokenBinders(null, TrailingCommentsBinder.INSTANCE$);
}
private boolean closeImportWithErrorIfNewline(PsiBuilder.Marker importDirective, String errorMessage) {
@@ -385,7 +385,7 @@ public class JetParsing extends AbstractJetParsing {
decl.drop();
}
else {
closeDeclarationWithCommentBinders(decl, declType);
closeDeclarationWithCommentBinders(decl, declType, true);
}
}
@@ -685,7 +685,7 @@ public class JetParsing extends AbstractJetParsing {
entryOrMember.drop();
}
else {
closeDeclarationWithCommentBinders(entryOrMember, type);
closeDeclarationWithCommentBinders(entryOrMember, type, true);
}
}
@@ -775,7 +775,7 @@ public class JetParsing extends AbstractJetParsing {
decl.drop();
}
else {
closeDeclarationWithCommentBinders(decl, declType);
closeDeclarationWithCommentBinders(decl, declType, true);
}
}
@@ -873,7 +873,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker objectDeclaration = mark();
parseObject(false, true);
closeDeclarationWithCommentBinders(objectDeclaration, OBJECT_DECLARATION);
closeDeclarationWithCommentBinders(objectDeclaration, OBJECT_DECLARATION, true);
return CLASS_OBJECT;
}
@@ -1078,7 +1078,7 @@ public class JetParsing extends AbstractJetParsing {
errorUntil("Accessor body expected", TokenSet.orSet(ACCESSOR_FIRST_OR_PROPERTY_END, TokenSet.create(LBRACE, LPAR, EQ)));
}
else {
getterOrSetter.done(PROPERTY_ACCESSOR);
closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true;
}
}
@@ -1110,7 +1110,7 @@ public class JetParsing extends AbstractJetParsing {
parseFunctionBody();
getterOrSetter.done(PROPERTY_ACCESSOR);
closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true;
}
@@ -1891,8 +1891,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker valueParameter = mark();
parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); // lazy, out, ref
parseTypeRef();
valueParameter.done(VALUE_PARAMETER);
valueParameter.setCustomEdgeTokenBinders(null, TrailingWhitespacesAndCommentsBinder.INSTANCE$);
closeDeclarationWithCommentBinders(valueParameter, VALUE_PARAMETER, false);
}
}
else {
@@ -1942,8 +1941,7 @@ public class JetParsing extends AbstractJetParsing {
return false;
}
parameter.done(VALUE_PARAMETER);
parameter.setCustomEdgeTokenBinders(null, TrailingWhitespacesAndCommentsBinder.INSTANCE$);
closeDeclarationWithCommentBinders(parameter, VALUE_PARAMETER, false);
return true;
}
+6 -6
View File
@@ -400,8 +400,8 @@ JetFile: CommentsBinding.kt
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// this is getter')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// this is getter')
PsiWhiteSpace('\n ')
PROPERTY_ACCESSOR
PsiElement(set)('set')
@@ -414,8 +414,8 @@ JetFile: CommentsBinding.kt
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// this is setter')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// this is setter')
PsiWhiteSpace('\n\n')
PROPERTY
PsiElement(val)('val')
@@ -441,5 +441,5 @@ JetFile: CommentsBinding.kt
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// prop2')
PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// prop2')
@@ -0,0 +1,40 @@
/**
* Doc comment for A
*/
// some comment
class A(
/**
* Doc comment for val-parameter
*/
val p: Int
) {
/**
* Doc comment for function
*/
fun foo() {
/**
* Doc comment for local function
*/
fun localFoo() { }
/**
* Doc comment for local class
*/
class LocalClass
}
/**
* Doc comment for property
*/
var property: Int
/** Doc comment for getter */
get() = 1
/** Doc comment for setter */
set(value) {}
}
/**
* Doc comment for B
*/
class B {
}
@@ -0,0 +1,169 @@
JetFile: DocCommentsBinding.kt
PACKAGE_DIRECTIVE
<empty list>
CLASS
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for A')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n')
PsiComment(EOL_COMMENT)('// some comment')
PsiWhiteSpace('\n')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('A')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiWhiteSpace('\n ')
VALUE_PARAMETER
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for val-parameter')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('p')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FUN
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for function')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
FUN
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for local function')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('localFoo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace(' ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n ')
CLASS
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for local class')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('LocalClass')
PsiWhiteSpace('\n ')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n ')
PROPERTY
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for property')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(var)('var')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('property')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiWhiteSpace('\n ')
PROPERTY_ACCESSOR
KDoc
PsiElement(KDOC_START)('/**')
PsiElement(KDOC_TEXT)(' Doc comment for getter ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(get)('get')
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace('\n ')
PROPERTY_ACCESSOR
KDoc
PsiElement(KDOC_START)('/**')
PsiElement(KDOC_TEXT)(' Doc comment for setter ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n ')
PsiElement(set)('set')
PsiElement(LPAR)('(')
VALUE_PARAMETER_LIST
VALUE_PARAMETER
PsiElement(IDENTIFIER)('value')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
CLASS
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' Doc comment for B')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
PsiWhiteSpace('\n')
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('B')
PsiWhiteSpace(' ')
CLASS_BODY
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n\n')
PsiElement(RBRACE)('}')
@@ -154,6 +154,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("DocCommentsBinding.kt")
public void testDocCommentsBinding() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DocCommentsBinding.kt");
doParsingTest(fileName);
}
@TestMetadata("DoubleColon.kt")
public void testDoubleColon() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DoubleColon.kt");
@@ -40,7 +40,6 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
@TestMetadata("AfterAs2.kt")
public void testAfterAs2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/smart/AfterAs2.kt");
doTest(fileName);
}