code review

This commit is contained in:
Dmitry Jemerov
2015-02-04 14:12:25 +01:00
parent c0e7d1faf2
commit 3253754395
16 changed files with 158 additions and 50 deletions
@@ -35,11 +35,11 @@ public interface KDocTokens {
ILazyParseableElementType KDOC = new ILazyParseableElementType("KDoc", JetLanguage.INSTANCE) {
@Override
public ASTNode parseContents(ASTNode chameleon) {
PsiElement parentElement = chameleon.getTreeParent().getPsi();
Project project = parentElement.getProject();
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, new KDocLexer(), getLanguage(),
chameleon.getText());
PsiParser parser = new KDocParser();
PsiElement parentElement = chameleon.getTreeParent().getPsi();
Project project = parentElement.getProject();
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, new KDocLexer(), getLanguage(),
chameleon.getText());
PsiParser parser = new KDocParser();
return parser.parse(this, builder).getFirstChildNode();
}
@@ -67,11 +67,11 @@ public interface KDocTokens {
ILazyParseableElementType MARKDOWN_LINK = new ILazyParseableElementType("KDOC_MARKDOWN_LINK", JetLanguage.INSTANCE) {
@Override
public ASTNode parseContents(ASTNode chameleon) {
PsiElement parentElement = chameleon.getTreeParent().getPsi();
Project project = parentElement.getProject();
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, new JetLexer(), getLanguage(),
chameleon.getText());
PsiParser parser = new KDocLinkParser();
PsiElement parentElement = chameleon.getTreeParent().getPsi();
Project project = parentElement.getProject();
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, new JetLexer(), getLanguage(),
chameleon.getText());
PsiParser parser = new KDocLinkParser();
return parser.parse(this, builder).getFirstChildNode();
}
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.lexer.JetTokens
*/
class KDocLinkParser(): PsiParser {
override fun parse(root: IElementType, builder: PsiBuilder): ASTNode {
builder.setDebugMode(true)
val rootMarker = builder.mark()
if (builder.getTokenType() == JetTokens.LBRACKET) {
builder.advanceLexer()
@@ -17,11 +17,15 @@
package org.jetbrains.kotlin.kdoc.psi.api;
import com.intellij.psi.PsiComment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection;
import org.jetbrains.kotlin.psi.JetDeclaration;
// Don't implement JetElement (or it will be treated as statement)
public interface KDoc extends PsiComment {
@Nullable
JetDeclaration getOwner();
@NotNull
KDocSection getDefaultSection();
}
@@ -35,7 +35,7 @@ public class KDocImpl(buffer: CharSequence?) : LazyParseablePsiElement(KDocToken
override fun getTokenType(): IElementType = JetTokens.DOC_COMMENT
override fun getOwner(): JetDeclaration = getParentOfType<JetDeclaration>(true)!!
override fun getOwner(): JetDeclaration? = getParentOfType<JetDeclaration>(true)
override fun getDefaultSection(): KDocSection = getChildOfType<KDocSection>()!!
}
@@ -30,7 +30,7 @@ public class KDocLink(node: ASTNode) : JetElementImpl(node) {
public fun getLinkTextRange(): TextRange {
val text = getText()
if (text.startsWith('[') && text.endsWith(']')) {
return TextRange(1, text.length()-1)
return TextRange(1, text.length() - 1)
}
return TextRange(0, text.length())
}
@@ -38,6 +38,10 @@ public class KDocName(node: ASTNode): JetElementImpl(node) {
public fun getQualifier(): KDocName? = getChildOfType()
/**
* Returns the range within the element containing the name (in other words,
* the range of the element excluding the qualifier and dot, if present).
*/
public fun getNameTextRange(): TextRange {
val dot = getNode().findChildByType(JetTokens.DOT)
val textRange = getTextRange()
@@ -54,9 +54,13 @@ public open class KDocTag(node: ASTNode) : KDocElementImpl(node) {
return null
}
public val knownTag: KDocKnownTag?
get() {
val name = getName()
return if (name != null) KDocKnownTag.findByTagName(name) else null
}
private fun hasSubject(contentChildren: List<ASTNode>): Boolean {
val name = getName()
val knownTag = if (name != null) KDocKnownTag.findByTagName(name) else null
if (knownTag?.isReferenceRequired() ?: false) {
return contentChildren.firstOrNull()?.getElementType() == KDocElementTypes.KDOC_LINK;
}
@@ -69,7 +73,7 @@ public open class KDocTag(node: ASTNode) : KDocElementImpl(node) {
.dropWhile { it.getElementType() == TokenType.WHITE_SPACE }
/**
* Returns the contents of this tag (all text following the tag name and the subject if present,
* Returns the content of this tag (all text following the tag name and the subject if present,
* with leading asterisks removed).
*/
public fun getContent(): String {
@@ -78,7 +78,7 @@ public class FunctionDescriptorUtil {
public static JetScope getFunctionInnerScope(
@NotNull JetScope outerScope,
@NotNull FunctionDescriptor descriptor,
RedeclarationHandler redeclarationHandler
@NotNull RedeclarationHandler redeclarationHandler
) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, redeclarationHandler, "Function inner scope");
ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
@@ -70,7 +70,7 @@ public final class JetScopeUtils {
public static JetScope getPropertyDeclarationInnerScope(
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull JetScope outerScope,
RedeclarationHandler redeclarationHandler
@NotNull RedeclarationHandler redeclarationHandler
) {
return getPropertyDeclarationInnerScope(propertyDescriptor,
outerScope,
@@ -119,7 +119,7 @@ public final class JetScopeUtils {
@NotNull JetScope outerScope,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@Nullable ReceiverParameterDescriptor receiver,
RedeclarationHandler redeclarationHandler,
@NotNull RedeclarationHandler redeclarationHandler,
boolean addLabelForProperty
) {
WritableScopeImpl result = new WritableScopeImpl(
@@ -0,0 +1,6 @@
/**
* [A.B.C...]
* [....]
* [A..B..C]
* [A.]
*/
@@ -0,0 +1,57 @@
JetFile: MarkdownLinkWithError.kt
PACKAGE_DIRECTIVE
<empty list>
KDoc
PsiElement(KDOC_START)('/**')
PsiWhiteSpace('\n ')
KDOC_SECTION
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
KDOC_NAME
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('B')
PsiElement(DOT)('.')
PsiElement(IDENTIFIER)('C')
PsiErrorElement:Closing bracket expected
<empty list>
PsiElement(RANGE)('..')
PsiElement(DOT)('.')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' [....]')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiErrorElement:Closing bracket expected
<empty list>
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('B')
PsiElement(RANGE)('..')
PsiElement(IDENTIFIER)('C')
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_LEADING_ASTERISK)('*')
PsiElement(KDOC_TEXT)(' ')
KDOC_LINK
KDOC_MARKDOWN_LINK
PsiElement(LBRACKET)('[')
KDOC_NAME
PsiElement(IDENTIFIER)('A')
PsiElement(DOT)('.')
PsiErrorElement:Identifier expected
<empty list>
PsiElement(RBRACKET)(']')
PsiWhiteSpace('\n ')
PsiElement(KDOC_END)('*/')
@@ -1085,6 +1085,12 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("MarkdownLinkWithError.kt")
public void testMarkdownLinkWithError() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/MarkdownLinkWithError.kt");
doParsingTest(fileName);
}
@TestMetadata("MarkdownQualifiedName.kt")
public void testMarkdownQualifiedName() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/kdoc/MarkdownQualifiedName.kt");
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
public class KDocReference(element: KDocName): JetMultiReference<KDocName>(element) {
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
@@ -54,7 +55,7 @@ public class KDocReference(element: KDocName): JetMultiReference<KDocName>(eleme
if (declaration == null) {
return arrayListOf()
}
val declarationDescriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
val kdocLink = getElement().getStrictParentOfType<KDocLink>()!!
return resolveKDocLink(session, declarationDescriptor, kdocLink.getTagIfSubject(), getElement().getQualifiedName())
}
@@ -75,7 +76,7 @@ public fun resolveKDocLink(session: KotlinCodeAnalyzer,
fromDescriptor: DeclarationDescriptor,
fromSubjectOfTag: KDocTag?,
qualifiedName: List<String>): Collection<DeclarationDescriptor> {
if (fromSubjectOfTag?.getName() == "param") {
if (fromSubjectOfTag?.knownTag == KDocKnownTag.PARAM) {
return resolveParamLink(fromDescriptor, qualifiedName)
}
@@ -90,19 +91,20 @@ public fun resolveKDocLink(session: KotlinCodeAnalyzer,
}
private fun resolveParamLink(fromDescriptor: DeclarationDescriptor, qualifiedName: List<String>): List<DeclarationDescriptor> {
if (qualifiedName.size() != 1) {
return listOf()
}
if (fromDescriptor is CallableDescriptor) {
val valueParams = fromDescriptor.getValueParameters().filter { it.getName().asString() == qualifiedName[0] }
if (valueParams.isNotEmpty()) {
return valueParams
}
}
if (fromDescriptor is ClassifierDescriptor) {
val typeParams = fromDescriptor.getTypeConstructor().getParameters().filter { it.getName().asString() == qualifiedName[0] }
if (typeParams.isNotEmpty()) {
return typeParams
// TODO resolve parameters of functions passed as parameters
val name = qualifiedName.singleOrNull() ?: return listOf()
when (fromDescriptor) {
is CallableDescriptor ->
return fromDescriptor.getValueParameters().filter { it.getName().asString() == name }
is ClassifierDescriptor -> {
val typeParams = fromDescriptor.getTypeConstructor().getParameters().filter { it.getName().asString() == name }
if (typeParams.isNotEmpty()) {
return typeParams
}
if (fromDescriptor is ClassDescriptor) {
return resolveParamLink(fromDescriptor.getUnsubstitutedPrimaryConstructor(), qualifiedName)
}
return listOf()
}
}
@@ -126,7 +128,6 @@ private fun getClassInnerScope(outerScope: JetScope, descriptor: ClassDescriptor
for (constructor in descriptor.getConstructors()) {
headerScope.addFunctionDescriptor(constructor)
}
headerScope.addLabeledDeclaration(descriptor)
headerScope.changeLockLevel(WritableScope.LockLevel.READING)
val classScope = ChainedScope(descriptor, "Class ${descriptor.getName()} scope", descriptor.getDefaultType().getMemberScope(), headerScope)
@@ -134,30 +135,30 @@ private fun getClassInnerScope(outerScope: JetScope, descriptor: ClassDescriptor
}
private fun getResolutionScope(session: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): JetScope {
when (descriptor) {
return when (descriptor) {
is PackageFragmentDescriptor ->
return getPackageInnerScope(descriptor)
getPackageInnerScope(descriptor)
is PackageViewDescriptor ->
return descriptor.getMemberScope()
descriptor.getMemberScope()
is ClassDescriptor ->
return getClassInnerScope(getOuterScope(descriptor, session), descriptor)
getClassInnerScope(getOuterScope(descriptor, session), descriptor)
is FunctionDescriptor ->
return FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(descriptor, session),
descriptor, RedeclarationHandler.DO_NOTHING)
FunctionDescriptorUtil.getFunctionInnerScope(getOuterScope(descriptor, session),
descriptor, RedeclarationHandler.DO_NOTHING)
is PropertyDescriptor ->
return JetScopeUtils.getPropertyDeclarationInnerScope(descriptor,
getOuterScope(descriptor, session),
RedeclarationHandler.DO_NOTHING)
JetScopeUtils.getPropertyDeclarationInnerScope(descriptor,
getOuterScope(descriptor, session),
RedeclarationHandler.DO_NOTHING)
is DeclarationDescriptorNonRoot ->
getOuterScope(descriptor, session)
else -> throw IllegalArgumentException("Cannot find resolution scope for root $descriptor")
}
if (descriptor is DeclarationDescriptorNonRoot)
return getOuterScope(descriptor, session)
throw IllegalArgumentException("Cannot find resolution scope for root $descriptor")
}
private fun getOuterScope(descriptor: DeclarationDescriptorWithSource, session: KotlinCodeAnalyzer): JetScope {
@@ -0,0 +1,7 @@
/**
* This is [<caret>Foo]
*/
class Foo {
}
// REF: (<root>).Foo
@@ -0,0 +1,7 @@
/**
* @param <caret>i this is an integer
*/
class C(i: Int) {
}
// REF: i
@@ -17,9 +17,10 @@
package org.jetbrains.kotlin.idea.kdoc;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.idea.resolve.AbstractReferenceResolveTest;
import org.jetbrains.kotlin.test.InnerTestClasses;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.idea.resolve.AbstractReferenceResolveTest;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
@@ -36,12 +37,24 @@ public class KdocResolveTestGenerated extends AbstractReferenceResolveTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/kdoc/resolve"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("ClassSelfReference.kt")
public void testClassSelfReference() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ClassSelfReference.kt");
doTest(fileName);
}
@TestMetadata("CodeReference.kt")
public void testCodeReference() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/CodeReference.kt");
doTest(fileName);
}
@TestMetadata("ConstructorParamReference.kt")
public void testConstructorParamReference() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ConstructorParamReference.kt");
doTest(fileName);
}
@TestMetadata("ImportedClassReference.kt")
public void testImportedClassReference() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/kdoc/resolve/ImportedClassReference.kt");