java: receiver parameter parsing

This commit is contained in:
Roman Shevchenko
2015-07-02 15:29:10 +03:00
parent 2a063c19d4
commit e737db6dcc
6 changed files with 213 additions and 9 deletions
@@ -15,10 +15,14 @@
*/
package com.intellij.psi;
import org.jetbrains.annotations.NotNull;
/**
* Represents a receiver parameter of a Java method (Java 8).
*
* @since 12.1
*/
public interface PsiReceiverParameter extends PsiVariable {
@NotNull
PsiThisExpression getIdentifier();
}
@@ -608,6 +608,22 @@ public class DeclarationParser {
}
}
if (typed) {
IElementType tokenType = builder.getTokenType();
if (tokenType == JavaTokenType.THIS_KEYWORD || tokenType == JavaTokenType.IDENTIFIER && builder.lookAhead(1) == JavaTokenType.DOT) {
PsiBuilder.Marker mark = builder.mark();
PsiBuilder.Marker expr = myParser.getExpressionParser().parse(builder);
if (expr != null && exprType(expr) == JavaElementType.THIS_EXPRESSION) {
mark.drop();
done(param, JavaElementType.RECEIVER_PARAMETER);
return param;
}
mark.rollbackTo();
}
}
if (expect(builder, JavaTokenType.IDENTIFIER)) {
if (!resource) {
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg ? "expected.rparen" : null);
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -30,6 +29,11 @@ public class PsiReceiverParameterImpl extends CompositePsiElement implements Psi
super(JavaElementType.RECEIVER_PARAMETER);
}
@NotNull
public PsiThisExpression getIdentifier() {
return PsiTreeUtil.getRequiredChildOfType(this, PsiThisExpression.class);
}
@Nullable
@Override
public PsiModifierList getModifierList() {
@@ -100,13 +104,6 @@ public class PsiReceiverParameterImpl extends CompositePsiElement implements Psi
return getIdentifier().getTextOffset();
}
@NotNull
private PsiElement getIdentifier() {
ASTNode node = findChildByType(JavaTokenType.THIS_KEYWORD);
assert node != null : getChildren();
return node.getPsi();
}
@Override
public String toString() {
return "PsiReceiverParameter";
@@ -0,0 +1,178 @@
PsiJavaFile:Receiver.java
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiMethod:m1
PsiModifierList:
<empty list>
PsiTypeParameterList
<empty list>
PsiTypeElement:void
PsiKeyword:void('void')
PsiWhiteSpace(' ')
PsiIdentifier:m1('m1')
PsiParameterList:(C this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:C
PsiJavaCodeReferenceElement:C
PsiIdentifier:C('C')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:this
PsiReferenceParameterList
<empty list>
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiReferenceList
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiMethod:m2
PsiModifierList:
<empty list>
PsiTypeParameterList
<empty list>
PsiTypeElement:void
PsiKeyword:void('void')
PsiWhiteSpace(' ')
PsiIdentifier:m2('m2')
PsiParameterList:(T T.this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:T.this
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiJavaToken:DOT('.')
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiReferenceList
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiMethod:m3
PsiModifierList:
<empty list>
PsiTypeParameterList
<empty list>
PsiTypeElement:void
PsiKeyword:void('void')
PsiWhiteSpace(' ')
PsiIdentifier:m3('m3')
PsiParameterList:(X Y.Z)
PsiJavaToken:LPARENTH('(')
PsiParameter:Y
PsiModifierList:
<empty list>
PsiTypeElement:X
PsiJavaCodeReferenceElement:X
PsiIdentifier:X('X')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:Y('Y')
PsiErrorElement:',' expected
PsiJavaToken:DOT('.')
PsiJavaCodeReferenceElement:Z
PsiIdentifier:Z('Z')
PsiReferenceParameterList
<empty list>
PsiJavaToken:RPARENTH(')')
PsiReferenceList
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiField:f1
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:f1('f1')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLambdaExpression:(T this) -> { }
PsiParameterList:(T this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:this
PsiReferenceParameterList
<empty list>
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiField:f2
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:f2('f2')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLambdaExpression:(T T.this) -> { }
PsiParameterList:(T T.this)
PsiJavaToken:LPARENTH('(')
PsiReceiverParameter
PsiModifierList:
<empty list>
PsiTypeElement:T
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiThisExpression:T.this
PsiJavaCodeReferenceElement:T
PsiIdentifier:T('T')
PsiReferenceParameterList
<empty list>
PsiJavaToken:DOT('.')
PsiKeyword:this('this')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
@@ -72,6 +72,15 @@ public class DeclarationParserTest extends JavaParsingTestCase {
" }\n} }");
}
public void testReceiver() {
doParserTest(
"{ void m1(C this);" +
" void m2(T T.this);" +
" void m3(X Y.Z);" +
" T f1 = (T this) -> { };" +
" T f2 = (T T.this) -> { }; }");
}
public void testFieldSimple() { doParserTest("{ int field = 0; }"); }
public void testFieldMulti() { doParserTest("{ int field1 = 0, field2; }"); }
public void testUnclosedBracket() { doParserTest("{ int field[ }"); }
@@ -371,7 +371,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
"\n" +
"class C<@A T extends @A C> implements @A I<@A T> {\n" +
" @TA T<@A T1, @A ? extends @A T2> f;\n" +
" @TA T m(/*@A C this,*/ @TA int p) throws @A E {\n" +
" @TA T m(@A C this, @TA int p) throws @A E {\n" +
" o.<@A1 C>m();\n" +
" new <T> @A2 C();\n" +
" C.@A3 B v = (@A4 C)v.new @A5 C();\n" +