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(); 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.done(elementType);
marker.setCustomEdgeTokenBinders(PrecedingWhitespacesAndCommentsBinder.INSTANCE$, TrailingWhitespacesAndCommentsBinder.INSTANCE$); marker.setCustomEdgeTokenBinders(precedingNonDocComments ? PrecedingCommentsBinder.INSTANCE$ : PrecedingDocCommentsBinder.INSTANCE$,
TrailingCommentsBinder.INSTANCE$);
} }
protected abstract JetParsing create(SemanticWhitespaceAwarePsiBuilder builder); protected abstract JetParsing create(SemanticWhitespaceAwarePsiBuilder builder);
@@ -21,7 +21,7 @@ import com.intellij.psi.tree.IElementType
import org.jetbrains.jet.lexer.JetTokens import org.jetbrains.jet.lexer.JetTokens
import com.intellij.openapi.util.text.StringUtil 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 { override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0 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 // Binds comments on the same line
object TrailingWhitespacesAndCommentsBinder : WhitespacesAndCommentsBinder { object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int { override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
if (tokens.isEmpty()) return 0 if (tokens.isEmpty()) return 0
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.parsing;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder;
import com.intellij.lang.WhitespacesAndCommentsBinder;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet; import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -960,13 +959,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected()); IElementType declType = parseLocalDeclarationRest(enumDetector.isDetected());
if (declType != null) { if (declType != null) {
decl.done(declType); // we do not attach preceding comments (non-doc) to local variables because they are likely commenting a few statements below
// we do not attach preceding comments to local variables because they are likely commenting a few statements below closeDeclarationWithCommentBinders(decl, declType, declType != JetNodeTypes.PROPERTY && declType != JetNodeTypes.MULTI_VARIABLE_DECLARATION);
WhitespacesAndCommentsBinder leftBinder = declType == JetNodeTypes.PROPERTY || declType == JetNodeTypes.MULTI_VARIABLE_DECLARATION
? null
: PrecedingWhitespacesAndCommentsBinder.INSTANCE$;
decl.setCustomEdgeTokenBinders(leftBinder,
TrailingWhitespacesAndCommentsBinder.INSTANCE$);
return true; return true;
} }
else { else {
@@ -211,7 +211,7 @@ public class JetParsing extends AbstractJetParsing {
packageDirective = mark(); packageDirective = mark();
packageDirective.done(PACKAGE_DIRECTIVE); packageDirective.done(PACKAGE_DIRECTIVE);
// this is necessary to allow comments at the start of the file to be bound to the first declaration: // 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(); parseImportDirectives();
@@ -318,7 +318,7 @@ public class JetParsing extends AbstractJetParsing {
} }
consumeIf(SEMICOLON); consumeIf(SEMICOLON);
importDirective.done(IMPORT_DIRECTIVE); importDirective.done(IMPORT_DIRECTIVE);
importDirective.setCustomEdgeTokenBinders(null, TrailingWhitespacesAndCommentsBinder.INSTANCE$); importDirective.setCustomEdgeTokenBinders(null, TrailingCommentsBinder.INSTANCE$);
} }
private boolean closeImportWithErrorIfNewline(PsiBuilder.Marker importDirective, String errorMessage) { private boolean closeImportWithErrorIfNewline(PsiBuilder.Marker importDirective, String errorMessage) {
@@ -385,7 +385,7 @@ public class JetParsing extends AbstractJetParsing {
decl.drop(); decl.drop();
} }
else { else {
closeDeclarationWithCommentBinders(decl, declType); closeDeclarationWithCommentBinders(decl, declType, true);
} }
} }
@@ -685,7 +685,7 @@ public class JetParsing extends AbstractJetParsing {
entryOrMember.drop(); entryOrMember.drop();
} }
else { else {
closeDeclarationWithCommentBinders(entryOrMember, type); closeDeclarationWithCommentBinders(entryOrMember, type, true);
} }
} }
@@ -775,7 +775,7 @@ public class JetParsing extends AbstractJetParsing {
decl.drop(); decl.drop();
} }
else { else {
closeDeclarationWithCommentBinders(decl, declType); closeDeclarationWithCommentBinders(decl, declType, true);
} }
} }
@@ -873,7 +873,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker objectDeclaration = mark(); PsiBuilder.Marker objectDeclaration = mark();
parseObject(false, true); parseObject(false, true);
closeDeclarationWithCommentBinders(objectDeclaration, OBJECT_DECLARATION); closeDeclarationWithCommentBinders(objectDeclaration, OBJECT_DECLARATION, true);
return CLASS_OBJECT; 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))); errorUntil("Accessor body expected", TokenSet.orSet(ACCESSOR_FIRST_OR_PROPERTY_END, TokenSet.create(LBRACE, LPAR, EQ)));
} }
else { else {
getterOrSetter.done(PROPERTY_ACCESSOR); closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true; return true;
} }
} }
@@ -1110,7 +1110,7 @@ public class JetParsing extends AbstractJetParsing {
parseFunctionBody(); parseFunctionBody();
getterOrSetter.done(PROPERTY_ACCESSOR); closeDeclarationWithCommentBinders(getterOrSetter, PROPERTY_ACCESSOR, false);
return true; return true;
} }
@@ -1891,8 +1891,7 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker valueParameter = mark(); PsiBuilder.Marker valueParameter = mark();
parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); // lazy, out, ref parseModifierList(MODIFIER_LIST, REGULAR_ANNOTATIONS_ONLY_WITH_BRACKETS); // lazy, out, ref
parseTypeRef(); parseTypeRef();
valueParameter.done(VALUE_PARAMETER); closeDeclarationWithCommentBinders(valueParameter, VALUE_PARAMETER, false);
valueParameter.setCustomEdgeTokenBinders(null, TrailingWhitespacesAndCommentsBinder.INSTANCE$);
} }
} }
else { else {
@@ -1942,8 +1941,7 @@ public class JetParsing extends AbstractJetParsing {
return false; return false;
} }
parameter.done(VALUE_PARAMETER); closeDeclarationWithCommentBinders(parameter, VALUE_PARAMETER, false);
parameter.setCustomEdgeTokenBinders(null, TrailingWhitespacesAndCommentsBinder.INSTANCE$);
return true; return true;
} }
+6 -6
View File
@@ -400,8 +400,8 @@ JetFile: CommentsBinding.kt
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
INTEGER_CONSTANT INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// this is getter') PsiComment(EOL_COMMENT)('// this is getter')
PsiWhiteSpace('\n ') PsiWhiteSpace('\n ')
PROPERTY_ACCESSOR PROPERTY_ACCESSOR
PsiElement(set)('set') PsiElement(set)('set')
@@ -414,8 +414,8 @@ JetFile: CommentsBinding.kt
BLOCK BLOCK
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}') PsiElement(RBRACE)('}')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// this is setter') PsiComment(EOL_COMMENT)('// this is setter')
PsiWhiteSpace('\n\n') PsiWhiteSpace('\n\n')
PROPERTY PROPERTY
PsiElement(val)('val') PsiElement(val)('val')
@@ -441,5 +441,5 @@ JetFile: CommentsBinding.kt
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
INTEGER_CONSTANT INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1') PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiComment(EOL_COMMENT)('// prop2') 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); doParsingTest(fileName);
} }
@TestMetadata("DocCommentsBinding.kt")
public void testDocCommentsBinding() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DocCommentsBinding.kt");
doParsingTest(fileName);
}
@TestMetadata("DoubleColon.kt") @TestMetadata("DoubleColon.kt")
public void testDoubleColon() throws Exception { public void testDoubleColon() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DoubleColon.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/DoubleColon.kt");
@@ -40,7 +40,6 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
@TestMetadata("AfterAs2.kt") @TestMetadata("AfterAs2.kt")
public void testAfterAs2() throws Exception { public void testAfterAs2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/smart/AfterAs2.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/smart/AfterAs2.kt");
doTest(fileName); doTest(fileName);
} }