Parse annotated multi-catch parameters

This commit is contained in:
Roman Shevchenko
2013-03-11 15:44:49 +01:00
parent 764b2ebf4e
commit c4b34d3f26
6 changed files with 311 additions and 28 deletions

View File

@@ -441,24 +441,24 @@ public class DeclarationParser {
}
@NotNull
public PsiBuilder.Marker parseParameterList(final PsiBuilder builder) {
return parseElementList(builder, ListType.NORMAL);
public PsiBuilder.Marker parseParameterList(PsiBuilder builder) {
return parseElementList(builder, ListType.METHOD);
}
@NotNull
public PsiBuilder.Marker parseResourceList(final PsiBuilder builder) {
public PsiBuilder.Marker parseResourceList(PsiBuilder builder) {
return parseElementList(builder, ListType.RESOURCE);
}
@NotNull
public PsiBuilder.Marker parseLambdaParameterList(final PsiBuilder builder, final boolean typed) {
public PsiBuilder.Marker parseLambdaParameterList(PsiBuilder builder, boolean typed) {
return parseElementList(builder, typed ? ListType.LAMBDA_TYPED : ListType.LAMBDA_UNTYPED);
}
private enum ListType { NORMAL, RESOURCE, LAMBDA_TYPED, LAMBDA_UNTYPED }
private enum ListType {METHOD, RESOURCE, LAMBDA_TYPED, LAMBDA_UNTYPED}
@NotNull
private PsiBuilder.Marker parseElementList(final PsiBuilder builder, final ListType type) {
private PsiBuilder.Marker parseElementList(PsiBuilder builder, ListType type) {
final boolean lambda = (type == ListType.LAMBDA_TYPED || type == ListType.LAMBDA_UNTYPED);
final boolean resources = (type == ListType.RESOURCE);
final PsiBuilder.Marker elementList = builder.mark();
@@ -559,29 +559,25 @@ public class DeclarationParser {
}
@Nullable
public PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) {
public PsiBuilder.Marker parseParameter(PsiBuilder builder, boolean ellipsis, boolean disjunctiveType) {
return parseListElement(builder, true, ellipsis, disjunctiveType, false);
}
@Nullable
public PsiBuilder.Marker parseResource(final PsiBuilder builder) {
public PsiBuilder.Marker parseResource(PsiBuilder builder) {
return parseListElement(builder, true, false, false, true);
}
@Nullable
public PsiBuilder.Marker parseLambdaParameter(final PsiBuilder builder, final boolean typed) {
public PsiBuilder.Marker parseLambdaParameter(PsiBuilder builder, boolean typed) {
return parseListElement(builder, typed, true, false, false);
}
@Nullable
private PsiBuilder.Marker parseListElement(final PsiBuilder builder,
final boolean typed,
final boolean ellipsis,
final boolean disjunctiveType,
final boolean resource) {
final PsiBuilder.Marker param = builder.mark();
private PsiBuilder.Marker parseListElement(PsiBuilder builder, boolean typed, boolean ellipsis, boolean disjunctiveType, boolean resource) {
PsiBuilder.Marker param = builder.mark();
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
ReferenceParser.TypeInfo typeInfo = null;
if (typed) {
@@ -626,8 +622,7 @@ public class DeclarationParser {
}
@Nullable
private PsiBuilder.Marker parseFieldOrLocalVariable(final PsiBuilder builder, final PsiBuilder.Marker declaration,
final int declarationStart, final Context context) {
private PsiBuilder.Marker parseFieldOrLocalVariable(PsiBuilder builder, PsiBuilder.Marker declaration, int declarationStart, Context context) {
final IElementType varType;
if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) {
varType = JavaElementType.FIELD;

View File

@@ -74,7 +74,8 @@ public class ReferenceParser {
while (builder.getTokenType() == operator) {
builder.advanceLexer();
if (builder.getTokenType() != JavaTokenType.IDENTIFIER) {
IElementType tokenType = builder.getTokenType();
if (tokenType != JavaTokenType.IDENTIFIER && tokenType != JavaTokenType.AT) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
parseTypeInfo(builder, flags, false);

View File

@@ -38,6 +38,13 @@ class SpecSamples {
m(@IllegalAnnotation java.util.@Vernal Date::getDay);
m(List<@English String>::size);
m(Arrays::<@NonNegative Integer>sort);
m((@TA Object x, @TB Object y) -> { System.out.println("x=" + x + " y=" + y); });
try { m(); }
catch (@A1 NullPointerException | @A2 IllegalArgumentException e) { }
try (@A Reader r = new @B FileReader("/dev/zero"); @A Writer w = new @B FileWriter("/dev/null")) { }
}
//
@@ -63,7 +70,7 @@ class SpecSamples {
@Immutable SpecSamples() { }
//
// todo[r.sh] 5. It is permitted to explicitly declare the method receiver as the first formal parameter ...
// todo [r.sh] 5. It is permitted to explicitly declare the method receiver as the first formal parameter ...
//
/*public String toString(@Readonly MyClass this) { }
@@ -78,7 +85,9 @@ class SpecSamples {
void innerMethod(@A Outer. @B Middle. @C Inner this) { }
}
}
}*/
}
void replace(@Readonly Object other, @Mutable MyClass this) { } // illegal */
//
// 6. It is permitted to write an annotation on a type parameter declaration ...

View File

@@ -1,4 +1,4 @@
PsiJavaFile:TypeAnno.java
PsiJavaFile:TypeAnnotations.java
PsiImportList
PsiImportStatement
PsiKeyword:import('import')
@@ -771,6 +771,277 @@ PsiJavaFile:TypeAnno.java
PsiIdentifier:sort('sort')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace('\n\n ')
PsiExpressionStatement
PsiMethodCallExpression:m((@TA Object x, @TB Object y) -> { System.out.println("x=" + x + " y=" + y); })
PsiReferenceExpression:m
PsiReferenceParameterList
<empty list>
PsiIdentifier:m('m')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiLambdaExpression:(@TA Object x, @TB Object y) -> { System.out.println("x=" + x + " y=" + y); }
PsiParameterList:(@TA Object x, @TB Object y)
PsiJavaToken:LPARENTH('(')
PsiParameter:x
PsiModifierList:@TA
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:TA
PsiIdentifier:TA('TA')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:Object
PsiJavaCodeReferenceElement:Object
PsiIdentifier:Object('Object')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:x('x')
PsiJavaToken:COMMA(',')
PsiWhiteSpace(' ')
PsiParameter:y
PsiModifierList:@TB
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:TB
PsiIdentifier:TB('TB')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:Object
PsiJavaCodeReferenceElement:Object
PsiIdentifier:Object('Object')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:y('y')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiJavaToken:ARROW('->')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiExpressionStatement
PsiMethodCallExpression:System.out.println("x=" + x + " y=" + y)
PsiReferenceExpression:System.out.println
PsiReferenceExpression:System.out
PsiReferenceExpression:System
PsiReferenceParameterList
<empty list>
PsiIdentifier:System('System')
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:out('out')
PsiJavaToken:DOT('.')
PsiReferenceParameterList
<empty list>
PsiIdentifier:println('println')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiPolyadicExpression: "x=" + x + " y=" + y
PsiLiteralExpression:"x="
PsiJavaToken:STRING_LITERAL('"x="')
PsiWhiteSpace(' ')
PsiJavaToken:PLUS('+')
PsiWhiteSpace(' ')
PsiReferenceExpression:x
PsiReferenceParameterList
<empty list>
PsiIdentifier:x('x')
PsiWhiteSpace(' ')
PsiJavaToken:PLUS('+')
PsiWhiteSpace(' ')
PsiLiteralExpression:" y="
PsiJavaToken:STRING_LITERAL('" y="')
PsiWhiteSpace(' ')
PsiJavaToken:PLUS('+')
PsiWhiteSpace(' ')
PsiReferenceExpression:y
PsiReferenceParameterList
<empty list>
PsiIdentifier:y('y')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace('\n\n ')
PsiTryStatement
PsiKeyword:try('try')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiExpressionStatement
PsiMethodCallExpression:m()
PsiReferenceExpression:m
PsiReferenceParameterList
<empty list>
PsiIdentifier:m('m')
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiWhiteSpace('\n ')
PsiCatchSection
PsiKeyword:catch('catch')
PsiWhiteSpace(' ')
PsiJavaToken:LPARENTH('(')
PsiParameter:e
PsiModifierList:@A1
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:A1
PsiIdentifier:A1('A1')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:NullPointerException | @A2 IllegalArgumentException
PsiTypeElement:NullPointerException
PsiJavaCodeReferenceElement:NullPointerException
PsiIdentifier:NullPointerException('NullPointerException')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaToken:OR('|')
PsiWhiteSpace(' ')
PsiTypeElement:@A2 IllegalArgumentException
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:A2
PsiIdentifier:A2('A2')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaCodeReferenceElement:IllegalArgumentException
PsiIdentifier:IllegalArgumentException('IllegalArgumentException')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:e('e')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiWhiteSpace('\n\n ')
PsiTryStatement
PsiKeyword:try('try')
PsiWhiteSpace(' ')
PsiResourceList:(@A Reader r = new @B FileReader("/dev/zero"); @A Writer w = new @B FileWriter("/dev/null"))
PsiJavaToken:LPARENTH('(')
PsiResourceVariable:r
PsiModifierList:@A
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:A
PsiIdentifier:A('A')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:Reader
PsiJavaCodeReferenceElement:Reader
PsiIdentifier:Reader('Reader')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r('r')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiNewExpression:new @B FileReader("/dev/zero")
PsiKeyword:new('new')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaCodeReferenceElement:@B FileReader
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:B
PsiIdentifier:B('B')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:FileReader('FileReader')
PsiReferenceParameterList
<empty list>
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiLiteralExpression:"/dev/zero"
PsiJavaToken:STRING_LITERAL('"/dev/zero"')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiResourceVariable:w
PsiModifierList:@A
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:A
PsiIdentifier:A('A')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:Writer
PsiJavaCodeReferenceElement:Writer
PsiIdentifier:Writer('Writer')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:w('w')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiNewExpression:new @B FileWriter("/dev/null")
PsiKeyword:new('new')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaCodeReferenceElement:@B FileWriter
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:B
PsiIdentifier:B('B')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:FileWriter('FileWriter')
PsiReferenceParameterList
<empty list>
PsiExpressionList
PsiJavaToken:LPARENTH('(')
PsiLiteralExpression:"/dev/null"
PsiJavaToken:STRING_LITERAL('"/dev/null"')
PsiJavaToken:RPARENTH(')')
PsiJavaToken:RPARENTH(')')
PsiWhiteSpace(' ')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiWhiteSpace(' ')
PsiJavaToken:RBRACE('}')
PsiWhiteSpace('\n ')
PsiJavaToken:RBRACE('}')
PsiWhiteSpace('\n\n ')
@@ -1099,11 +1370,11 @@ PsiJavaFile:TypeAnno.java
PsiWhiteSpace('\n\n ')
PsiComment(END_OF_LINE_COMMENT)('//')
PsiWhiteSpace('\n ')
PsiComment(END_OF_LINE_COMMENT)('// todo[r.sh] 5. It is permitted to explicitly declare the method receiver as the first formal parameter ...')
PsiComment(END_OF_LINE_COMMENT)('// todo [r.sh] 5. It is permitted to explicitly declare the method receiver as the first formal parameter ...')
PsiWhiteSpace('\n ')
PsiComment(END_OF_LINE_COMMENT)('//')
PsiWhiteSpace('\n\n ')
PsiComment(C_STYLE_COMMENT)('/*public String toString(@Readonly MyClass this) { }\n\n public boolean equals(@Readonly MyClass this, @Readonly Object other) { }\n\n SpecSamples(@Receiver SpecSamples this, boolean b) { }\n\n class Outer {\n class Middle {\n class Inner {\n void innerMethod(@A Outer. @B Middle. @C Inner this) { }\n }\n }\n }*/')
PsiComment(C_STYLE_COMMENT)('/*public String toString(@Readonly MyClass this) { }\n\n public boolean equals(@Readonly MyClass this, @Readonly Object other) { }\n\n SpecSamples(@Receiver SpecSamples this, boolean b) { }\n\n class Outer {\n class Middle {\n class Inner {\n void innerMethod(@A Outer. @B Middle. @C Inner this) { }\n }\n }\n }\n\n void replace(@Readonly Object other, @Mutable MyClass this) { } // illegal */')
PsiWhiteSpace('\n\n ')
PsiComment(END_OF_LINE_COMMENT)('//')
PsiWhiteSpace('\n ')

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -38,5 +38,5 @@ public class AnnotationParsingTest extends JavaParsingTestCase {
public void testQualifiedAnnotation() { doTest(true); }
public void testEnumSmartTypeCompletion() { doTest(true); }
public void testErrors() { doTest(true); }
public void testTypeAnno() { doTest(true); }
public void testTypeAnnotations() { doTest(true); }
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 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.
@@ -34,7 +34,14 @@ public class BitUtil {
/**
* @return {@code value} with the bit corresponding to the {@code mask} set (if setBit is true) or cleared (if setBit is false)
*/
public static int set(final int value, final int mask, boolean setBit) {
public static int set(int value, int mask, boolean setBit) {
return setBit ? value | mask : value & ~mask;
}
/**
* @return {@code value} with the bit corresponding to the {@code mask} set (if setBit is true) or cleared (if setBit is false)
*/
public static byte set(byte value, byte mask, boolean setBit) {
return (byte)(setBit ? value | mask : value & ~mask);
}
}