Project Coin try-with-resource support (parser, PSI)

This commit is contained in:
Roman Shevchenko
2011-02-18 14:10:58 +01:00
parent 409d194aa2
commit 40046e9177
25 changed files with 471 additions and 50 deletions

View File

@@ -447,26 +447,43 @@ public class DeclarationParser {
@NotNull
public static PsiBuilder.Marker parseParameterList(final PsiBuilder builder) {
return parseParameterList(builder, false);
}
@NotNull
public static PsiBuilder.Marker parseResourceList(final PsiBuilder builder) {
return parseParameterList(builder, true);
}
@NotNull
private static PsiBuilder.Marker parseParameterList(final PsiBuilder builder, final boolean resources) {
assert builder.getTokenType() == JavaTokenType.LPARENTH : builder.getTokenType();
final PsiBuilder.Marker paramList = builder.mark();
builder.advanceLexer();
final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA;
final String noDelimiterMsg = JavaErrorMessages.message(resources ? "expected.semicolon" : "expected.comma");
final String noParameterMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter");
PsiBuilder.Marker invalidElements = null;
String errorMessage = null;
boolean commaExpected = false;
boolean delimiterExpected = false;
int paramCount = 0;
while (true) {
final IElementType tokenType = builder.getTokenType();
if (tokenType == null || tokenType == JavaTokenType.RPARENTH) {
boolean noLastParam = !commaExpected && paramCount > 0;
if (tokenType == null || tokenType == JavaTokenType.RPARENTH || tokenType == JavaTokenType.LBRACE) {
boolean noLastParam = !delimiterExpected && paramCount > 0;
if (noLastParam) {
error(builder, JavaErrorMessages.message("expected.identifier.or.type"));
}
if (tokenType == JavaTokenType.RPARENTH) {
if (invalidElements != null) {
invalidElements.error(errorMessage);
invalidElements = null;
}
else if (resources && paramCount == 0) {
error(builder, JavaErrorMessages.message("expected.resource"));
}
invalidElements = null;
builder.advanceLexer();
}
else {
@@ -481,9 +498,9 @@ public class DeclarationParser {
break;
}
if (commaExpected) {
if (builder.getTokenType() == JavaTokenType.COMMA) {
commaExpected = false;
if (delimiterExpected) {
if (builder.getTokenType() == delimiter) {
delimiterExpected = false;
if (invalidElements != null) {
invalidElements.error(errorMessage);
invalidElements = null;
@@ -493,9 +510,9 @@ public class DeclarationParser {
}
}
else {
final PsiBuilder.Marker param = parseParameter(builder, true, false);
final PsiBuilder.Marker param = parseParameter(builder, true, false, resources);
if (param != null) {
commaExpected = true;
delimiterExpected = true;
if (invalidElements != null) {
invalidElements.errorBefore(errorMessage, param);
invalidElements = null;
@@ -506,14 +523,14 @@ public class DeclarationParser {
}
if (invalidElements == null) {
if (builder.getTokenType() == JavaTokenType.COMMA) {
error(builder, JavaErrorMessages.message("expected.parameter"));
if (builder.getTokenType() == delimiter) {
error(builder, noParameterMsg);
builder.advanceLexer();
continue;
}
else {
invalidElements = builder.mark();
errorMessage = commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter");
errorMessage = delimiterExpected ? noDelimiterMsg : noParameterMsg;
}
}
@@ -533,14 +550,14 @@ public class DeclarationParser {
}
@Nullable
public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) {
public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunction, final boolean value) {
final PsiBuilder.Marker param = builder.mark();
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
int flags = ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD;
if (ellipsis) flags |= ReferenceParser.ELLIPSIS;
if (disjunctiveType) flags |= ReferenceParser.DISJUNCTIONS;
if (disjunction) flags |= ReferenceParser.DISJUNCTIONS;
final ReferenceParser.TypeInfo typeInfo = ReferenceParser.parseTypeInfo(builder, flags);
if (typeInfo == null) {
@@ -555,15 +572,23 @@ public class DeclarationParser {
}
if (expect(builder, JavaTokenType.IDENTIFIER)) {
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen"));
done(param, JavaElementType.PARAMETER);
return param;
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg || value, JavaErrorMessages.message("expected.rparen"));
if (value) {
if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) {
if (ExpressionParser.parse(builder) == null) {
error(builder, JavaErrorMessages.message("expected.expression"));
}
}
}
}
else {
error(builder, JavaErrorMessages.message("expected.identifier"));
param.drop();
return modListInfo.first;
}
done(param, JavaElementType.PARAMETER);
return param;
}
@Nullable

View File

@@ -138,14 +138,16 @@ public class JavaParserUtil {
builder.putUserDataUnprotected(LANG_LEVEL_KEY, level);
}
// todo[r.sh] join all JDK 7 check clauses into single method (IDEA 11)
public static boolean areDiamondsSupported(final PsiBuilder builder) {
return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_7);
}
// todo[r.sh] join all JDK 7 check clauses into single method (IDEA 11)
public static boolean areMultiCatchSupported(final PsiBuilder builder) {
return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_7);
}
public static boolean areTryWithResourcesSupported(final PsiBuilder builder) {
return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_7);
}
public static boolean areTypeAnnotationsSupported(final PsiBuilder builder) {
return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_8);

View File

@@ -375,7 +375,7 @@ public class StatementParser {
}
final PsiBuilder.Marker afterParenth = builder.mark();
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, false);
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, false, false);
if (param == null || JavaParserUtil.exprType(param) != JavaElementType.PARAMETER || builder.getTokenType() != JavaTokenType.COLON) {
afterParenth.rollbackTo();
return parseForLoopFromInitialization(builder, statement);
@@ -612,6 +612,12 @@ public class StatementParser {
final PsiBuilder.Marker statement = builder.mark();
builder.advanceLexer();
boolean hasResourceList = false;
if (areTryWithResourcesSupported(builder) && builder.getTokenType() == JavaTokenType.LPARENTH) {
hasResourceList = true;
DeclarationParser.parseResourceList(builder);
}
final PsiBuilder.Marker tryBlock = parseCodeBlock(builder, true);
if (tryBlock == null) {
error(builder, JavaErrorMessages.message("expected.lbrace"));
@@ -619,7 +625,7 @@ public class StatementParser {
return statement;
}
if (!TRY_CLOSERS_SET.contains(builder.getTokenType())) {
if (!hasResourceList && !TRY_CLOSERS_SET.contains(builder.getTokenType())) {
error(builder, JavaErrorMessages.message("expected.catch.or.finally"));
done(statement, JavaElementType.TRY_STATEMENT);
return statement;
@@ -651,7 +657,7 @@ public class StatementParser {
return false;
}
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, areMultiCatchSupported(builder));
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, areMultiCatchSupported(builder), false);
if (param == null) {
error(builder, JavaErrorMessages.message("expected.parameter"));
}

View File

@@ -173,11 +173,11 @@ public class PsiImplUtil {
return processor.getResults().toArray();
}
public static boolean processDeclarationsInMethod(PsiMethod method,
@NotNull PsiScopeProcessor processor,
ResolveState state,
PsiElement lastParent,
PsiElement place) {
public static boolean processDeclarationsInMethod(@NotNull final PsiMethod method,
@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state,
final PsiElement lastParent,
@NotNull final PsiElement place) {
final ElementClassHint hint = processor.getHint(ElementClassHint.KEY);
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, method);
if (hint == null || hint.shouldProcess(ElementClassHint.DeclaractionKind.CLASS)) {
@@ -185,15 +185,35 @@ public class PsiImplUtil {
if (list != null && !list.processDeclarations(processor, state, null, place)) return false;
}
if (lastParent instanceof PsiCodeBlock) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
for (PsiParameter parameter : parameters) {
if (!processor.execute(parameter, state)) return false;
}
final PsiParameterList parameterList = method.getParameterList();
if (processDeclarationsInParameterList(parameterList, processor, state)) return false;
}
return true;
}
public static boolean processDeclarationsInTryStatement(@NotNull final PsiTryStatement statement,
@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state,
final PsiElement lastParent) {
if (lastParent instanceof PsiCodeBlock) {
final PsiParameterList parameterList = statement.getResourceList();
if (parameterList != null && processDeclarationsInParameterList(parameterList, processor, state)) return false;
}
return true;
}
private static boolean processDeclarationsInParameterList(@NotNull final PsiParameterList parameterList,
@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state) {
final PsiParameter[] parameters = parameterList.getParameters();
for (PsiParameter parameter : parameters) {
if (!processor.execute(parameter, state)) return true;
}
return false;
}
public static boolean hasTypeParameters(@NotNull PsiTypeParameterListOwner owner) {
final PsiTypeParameterList typeParameterList = owner.getTypeParameterList();
return typeParameterList != null && typeParameterList.getTypeParameters().length != 0;

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl;
import com.intellij.ide.fileTemplates.FileTemplate;
@@ -45,7 +44,7 @@ import java.util.Properties;
import static com.intellij.openapi.util.text.StringUtil.join;
/*
/**
* @author max
*/
public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJavaParserFacade {
@@ -61,7 +60,14 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
private static final JavaParserUtil.ParserWrapper PARAMETER = new JavaParserUtil.ParserWrapper() {
@Override
public void parse(final PsiBuilder builder) {
DeclarationParser.parseParameter(builder, true, false);
DeclarationParser.parseParameter(builder, true, false, false);
}
};
private static final JavaParserUtil.ParserWrapper RESOURCE = new JavaParserUtil.ParserWrapper() {
@Override
public void parse(final PsiBuilder builder) {
DeclarationParser.parseParameter(builder, true, false, true);
}
};
@@ -233,7 +239,10 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context);
final boolean resource = context instanceof PsiParameterList &&
context.getParent() instanceof PsiTryStatement;
final JavaParserUtil.ParserWrapper wrapper = resource ? RESOURCE : PARAMETER;
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiParameter)) {
throw new IncorrectOperationException("Incorrect parameter \"" + text + "\".");

View File

@@ -49,10 +49,7 @@ public class JavaLightStubBuilder extends LightStubBuilder {
@Override
public boolean skipChildProcessingWhenBuildingStubs(final IElementType nodeType, final IElementType childType) {
if (childType == JavaElementType.PARAMETER && nodeType != JavaElementType.PARAMETER_LIST) {
return true;
}
return false;
return childType == JavaElementType.PARAMETER_LIST && nodeType != JavaElementType.METHOD && nodeType != JavaElementType.ANNOTATION_METHOD ||
childType == JavaElementType.PARAMETER && nodeType != JavaElementType.PARAMETER_LIST;
}
}

View File

@@ -18,29 +18,33 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.Constants;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
public class PsiTryStatementImpl extends CompositePsiElement implements PsiTryStatement, Constants {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiTryStatementImpl");
private volatile PsiParameter[] myCachedCatchParameters = null;
public PsiTryStatementImpl() {
super(TRY_STATEMENT);
}
public void clearCaches() {
super.clearCaches();
myCachedCatchParameters = null;
}
public PsiTryStatementImpl() {
super(TRY_STATEMENT);
}
public PsiCodeBlock getTryBlock() {
return (PsiCodeBlock)findChildByRoleAsPsiElement(ChildRole.TRY_BLOCK);
}
@@ -88,6 +92,11 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt
return (PsiCodeBlock)findChildByRoleAsPsiElement(ChildRole.FINALLY_BLOCK);
}
@Override
public PsiParameterList getResourceList() {
return PsiTreeUtil.findChildOfType(this, PsiParameterList.class);
}
public ASTNode findChildByRole(int role) {
LOG.assertTrue(ChildRole.isUnique(role));
switch(role){
@@ -150,6 +159,14 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt
}
}
@Override
public boolean processDeclarations(@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state,
final PsiElement lastParent,
@NotNull final PsiElement place) {
return PsiImplUtil.processDeclarationsInTryStatement(this, processor, state, lastParent);
}
public String toString() {
return "PsiTryStatement";
}

View File

@@ -0,0 +1,10 @@
PsiJavaFile:TryIncomplete10.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(
PsiJavaToken:LPARENTH('(')
PsiErrorElement:')' expected
<empty list>
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,11 @@
PsiJavaFile:TryIncomplete11.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:()
PsiJavaToken:LPARENTH('(')
PsiErrorElement:Resource definition expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,14 @@
PsiJavaFile:TryIncomplete12.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(;)
PsiJavaToken:LPARENTH('(')
PsiErrorElement:Resource definition expected
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiErrorElement:Resource definition expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,18 @@
PsiJavaFile:TryIncomplete13.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(final )
PsiJavaToken:LPARENTH('(')
PsiModifierList:final
PsiKeyword:final('final')
PsiErrorElement:Type expected
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:
<empty list>
PsiErrorElement:Identifier expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,18 @@
PsiJavaFile:TryIncomplete14.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(R)
PsiJavaToken:LPARENTH('(')
PsiModifierList:
<empty list>
PsiTypeElement:R
PsiJavaCodeReferenceElement:R
PsiIdentifier:R('R')
PsiReferenceParameterList
<empty list>
PsiErrorElement:Identifier expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,21 @@
PsiJavaFile:TryIncomplete15.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(R r)
PsiJavaToken:LPARENTH('(')
PsiParameter:r
PsiModifierList:
<empty list>
PsiTypeElement:R
PsiJavaCodeReferenceElement:R
PsiIdentifier:R('R')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r('r')
PsiErrorElement:'=' expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,23 @@
PsiJavaFile:TryIncomplete16.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(R r =)
PsiJavaToken:LPARENTH('(')
PsiParameter:r
PsiModifierList:
<empty list>
PsiTypeElement:R
PsiJavaCodeReferenceElement:R
PsiIdentifier:R('R')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r('r')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiErrorElement:Expression expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,27 @@
PsiJavaFile:TryIncomplete17.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(R r = 0;)
PsiJavaToken:LPARENTH('(')
PsiParameter:r
PsiModifierList:
<empty list>
PsiTypeElement:R
PsiJavaCodeReferenceElement:R
PsiIdentifier:R('R')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r('r')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLiteralExpression:0
PsiJavaToken:INTEGER_LITERAL('0')
PsiJavaToken:SEMICOLON(';')
PsiErrorElement:Identifier or type expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,25 @@
PsiJavaFile:TryIncomplete8.java
PsiTryStatement
PsiKeyword:try('try')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')
PsiCatchSection
PsiKeyword:catch('catch')
PsiJavaToken:LPARENTH('(')
PsiModifierList:
<empty list>
PsiTypeElement:A|
PsiTypeElement:A
PsiJavaCodeReferenceElement:A
PsiIdentifier:A('A')
PsiReferenceParameterList
<empty list>
PsiJavaToken:OR('|')
PsiErrorElement:Identifier expected
<empty list>
PsiErrorElement:Identifier expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiErrorElement:'{' expected
<empty list>

View File

@@ -0,0 +1,28 @@
PsiJavaFile:TryIncomplete9.java
PsiTryStatement
PsiKeyword:try('try')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')
PsiCatchSection
PsiKeyword:catch('catch')
PsiJavaToken:LPARENTH('(')
PsiModifierList:
<empty list>
PsiTypeElement:A|B
PsiTypeElement:A
PsiJavaCodeReferenceElement:A
PsiIdentifier:A('A')
PsiReferenceParameterList
<empty list>
PsiJavaToken:OR('|')
PsiTypeElement:B
PsiJavaCodeReferenceElement:B
PsiIdentifier:B('B')
PsiReferenceParameterList
<empty list>
PsiErrorElement:Identifier expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiErrorElement:'{' expected
<empty list>

View File

@@ -8,8 +8,9 @@ PsiJavaFile:TryNormal1.java
PsiKeyword:catch('catch')
PsiJavaToken:LPARENTH('(')
PsiParameter:e
PsiModifierList:
<empty list>
PsiModifierList:final
PsiKeyword:final('final')
PsiWhiteSpace(' ')
PsiTypeElement:E
PsiJavaCodeReferenceElement:E
PsiIdentifier:E('E')
@@ -24,4 +25,4 @@ PsiJavaFile:TryNormal1.java
PsiKeyword:finally('finally')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,30 @@
PsiJavaFile:TryNormal3.java
PsiTryStatement
PsiKeyword:try('try')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')
PsiCatchSection
PsiKeyword:catch('catch')
PsiJavaToken:LPARENTH('(')
PsiParameter:e
PsiModifierList:
<empty list>
PsiTypeElement:A|B
PsiTypeElement:A
PsiJavaCodeReferenceElement:A
PsiIdentifier:A('A')
PsiReferenceParameterList
<empty list>
PsiJavaToken:OR('|')
PsiTypeElement:B
PsiJavaCodeReferenceElement:B
PsiIdentifier:B('B')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:e('e')
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,24 @@
PsiJavaFile:TryNormal4.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(R r = 0)
PsiJavaToken:LPARENTH('(')
PsiParameter:r
PsiModifierList:
<empty list>
PsiTypeElement:R
PsiJavaCodeReferenceElement:R
PsiIdentifier:R('R')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r('r')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLiteralExpression:0
PsiJavaToken:INTEGER_LITERAL('0')
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -0,0 +1,41 @@
PsiJavaFile:TryNormal5.java
PsiTryStatement
PsiKeyword:try('try')
PsiParameterList:(R1 r1 = 1; R2 r2 = 2)
PsiJavaToken:LPARENTH('(')
PsiParameter:r1
PsiModifierList:
<empty list>
PsiTypeElement:R1
PsiJavaCodeReferenceElement:R1
PsiIdentifier:R1('R1')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r1('r1')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLiteralExpression:1
PsiJavaToken:INTEGER_LITERAL('1')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiParameter:r2
PsiModifierList:
<empty list>
PsiTypeElement:R2
PsiJavaCodeReferenceElement:R2
PsiIdentifier:R2('R2')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r2('r2')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLiteralExpression:2
PsiJavaToken:INTEGER_LITERAL('2')
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')

View File

@@ -18,6 +18,7 @@ package com.intellij.lang.java.parser.partial;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.java.parser.JavaParsingTestCase;
import com.intellij.lang.java.parser.StatementParser;
import com.intellij.pom.java.LanguageLevel;
public class StatementParserTest extends JavaParsingTestCase {
@@ -116,8 +117,11 @@ public class StatementParserTest extends JavaParsingTestCase {
public void testThrowIncomplete1() { doParserTest("throw e"); }
public void testTryNormal0() { doParserTest("try{}catch(E e){}"); }
public void testTryNormal1() { doParserTest("try{}catch(E e){}finally{}"); }
public void testTryNormal1() { doParserTest("try{}catch(final E e){}finally{}"); }
public void testTryNormal2() { doParserTest("try{}finally{}"); }
public void testTryNormal3() { doParserTestJDK7("try{}catch(A|B e){}"); }
public void testTryNormal4() { doParserTestJDK7("try(R r = 0){}"); }
public void testTryNormal5() { doParserTestJDK7("try(R1 r1 = 1; R2 r2 = 2){}"); }
public void testTryIncomplete0() { doParserTest("try"); }
public void testTryIncomplete1() { doParserTest("try{}"); }
public void testTryIncomplete2() { doParserTest("try{}catch"); }
@@ -126,6 +130,16 @@ public class StatementParserTest extends JavaParsingTestCase {
public void testTryIncomplete5() { doParserTest("try{}catch(E e"); }
public void testTryIncomplete6() { doParserTest("try{}catch(E e)"); }
public void testTryIncomplete7() { doParserTest("try{}finally"); }
public void testTryIncomplete8() { doParserTestJDK7("try{}catch(A|)"); }
public void testTryIncomplete9() { doParserTestJDK7("try{}catch(A|B)"); }
public void testTryIncomplete10() { doParserTestJDK7("try({}"); }
public void testTryIncomplete11() { doParserTestJDK7("try(){}"); }
public void testTryIncomplete12() { doParserTestJDK7("try(;){}"); }
public void testTryIncomplete13() { doParserTestJDK7("try(final ){}"); }
public void testTryIncomplete14() { doParserTestJDK7("try(R){}"); }
public void testTryIncomplete15() { doParserTestJDK7("try(R r){}"); }
public void testTryIncomplete16() { doParserTestJDK7("try(R r =){}"); }
public void testTryIncomplete17() { doParserTestJDK7("try(R r = 0;){}"); }
public void testWhileNormal() { doParserTest("while (true) foo();"); }
public void testWhileIncomplete0() { doParserTest("while"); }
@@ -152,4 +166,13 @@ public class StatementParserTest extends JavaParsingTestCase {
}
});
}
private void doParserTestJDK7(final String text) {
withLevel(LanguageLevel.JDK_1_7, new Runnable() {
@Override
public void run() {
doParserTest(text);
}
});
}
}

View File

@@ -296,6 +296,28 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
});
}
public void testNonMethodParameterLists() {
withLevel(LanguageLevel.JDK_1_7, new Runnable() {
@Override public void run() {
doTest("class C {\n" +
" {\n" +
" try (Resource r = new Resource()) { }\n" +
" }\n" +
"}",
"PsiJavaFileStub []\n" +
" IMPORT_LIST:PsiImportListStub\n" +
" CLASS:PsiClassStub[name=C fqn=C]\n" +
" MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" +
" TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" +
" EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" +
" IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" +
" CLASS_INITIALIZER:PsiClassInitializerStub\n" +
" MODIFIER_LIST:PsiModifierListStub[mask=4096]\n");
}
});
}
public void testSOEProof() {
final StringBuilder sb = new StringBuilder();
final SecureRandom random = new SecureRandom();

View File

@@ -64,4 +64,12 @@ public interface PsiTryStatement extends PsiStatement {
*/
@Nullable
PsiCodeBlock getFinallyBlock();
/**
* Returns a resource list of try-with-resources statement.
*
* @return resource list, or null if the statement doesn't have it.
*/
@Nullable
PsiParameterList getResourceList();
}

View File

@@ -310,6 +310,7 @@ unexpected.identifier=Unexpected identifier
expected.gt='>' expected.
expected.lbrace.or.semicolon='{' or ';' expected
expected.parameter=Parameter expected
expected.resource=Resource definition expected
expected.type.parameter=Type parameter expected
expected.comma=',' expected
expected.comma.or.rparen=',' or ')' expected