Project Coin try-with-resource support, take 4

This commit is contained in:
Roman Shevchenko
2011-02-24 20:02:33 +01:00
parent 695ee8b40f
commit 9e0bef7dcd
38 changed files with 316 additions and 415 deletions
@@ -246,8 +246,8 @@ public class ExceptionUtil {
unhandledExceptions = unhandled;
}
if (element instanceof PsiResource) {
final List<PsiClassType> unhandled = getUnhandledCloserExceptions((PsiResource)element, topElement);
if (element instanceof PsiResourceVariable) {
final List<PsiClassType> unhandled = getUnhandledCloserExceptions((PsiResourceVariable)element, topElement);
if (unhandledExceptions == null) {
unhandledExceptions = unhandled;
}
@@ -331,7 +331,7 @@ public class ExceptionUtil {
}
@NotNull
public static List<PsiClassType> getUnhandledCloserExceptions(final PsiResource resource, final PsiElement topElement) {
public static List<PsiClassType> getUnhandledCloserExceptions(final PsiResourceVariable resource, final PsiElement topElement) {
final PsiType resourceType = resource.getType();
if (resourceType instanceof PsiClassType) {
final PsiClass resourceClass = ((PsiClassType)resourceType).resolve();
@@ -675,8 +675,8 @@ public class HighlightControlFlowUtil {
@Nullable
public static PsiClass getInnerClassVariableReferencedFrom(PsiVariable variable, PsiElement context) {
PsiElement[] scope;
if (variable instanceof PsiScopedLocalVariable) {
scope = ((PsiScopedLocalVariable)variable).getDeclarationScope();
if (variable instanceof PsiResourceVariable) {
scope = ((PsiResourceVariable)variable).getDeclarationScope();
}
else if (variable instanceof PsiLocalVariable) {
scope = new PsiElement[]{variable.getParent().getParent()}; // code block or for statement
@@ -435,7 +435,7 @@ public class HighlightUtil {
@Nullable
static HighlightInfo checkVariableInitializerType(PsiVariable variable) {
PsiExpression initializer = variable.getInitializer();
// array initalizer checked in checkArrayInitializerApplicable
// array initializer checked in checkArrayInitializerApplicable
if (initializer == null || initializer instanceof PsiArrayInitializerExpression) return null;
PsiType lType = variable.getType();
PsiType rType = initializer.getType();
@@ -655,7 +655,7 @@ public class HighlightUtil {
}
@Nullable
public static HighlightInfo checkUnhandledCloserExceptions(final PsiResource resource) {
public static HighlightInfo checkUnhandledCloserExceptions(final PsiResourceVariable resource) {
final List<PsiClassType> unhandled = ExceptionUtil.getUnhandledCloserExceptions(resource, null);
if (unhandled.isEmpty()) return null;
@@ -1148,7 +1148,7 @@ public class HighlightUtil {
}
@Nullable
public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiResource resource) {
public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiResourceVariable resource) {
final PsiType type = resource.getType();
if (type == null) return null;
@@ -906,11 +906,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
@Override
public void visitResource(final PsiResource resource) {
myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource));
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource));
}
public void visitResourceVariable(final PsiResourceVariable resourceVariable) {
visitVariable(resourceVariable);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resourceVariable));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resourceVariable));
}
@Override public void visitTypeElement(PsiTypeElement type) {
@@ -57,7 +57,7 @@ public class ReuseVariableDeclarationFix implements IntentionAction {
return myVariable != null &&
myVariable.isValid() &&
myVariable instanceof PsiLocalVariable &&
!(myVariable.getParent() instanceof PsiResource && myVariable.getInitializer() == null) &&
!(myVariable.getParent() instanceof PsiResourceVariable && myVariable.getInitializer() == null) &&
previousVariable != null &&
Comparing.equal(previousVariable.getType(), myVariable.getType()) &&
myIdentifier != null &&
@@ -82,7 +82,7 @@ public class ReuseVariableDeclarationFix implements IntentionAction {
final PsiElementFactory factory = JavaPsiFacade.getInstance(myVariable.getProject()).getElementFactory();
final PsiElement replacement;
final PsiElement parent = myVariable.getParent();
if (parent instanceof PsiResource) {
if (parent instanceof PsiResourceVariable) {
replacement = factory.createResourceFromText(myVariable.getName() + " = " + initializer.getText(), null);
}
else {
@@ -97,7 +97,7 @@ public class DefUseInspection extends BaseLocalInspectionTool {
PsiElement context = info.getContext();
PsiVariable psiVariable = info.getVariable();
if (context instanceof PsiDeclarationStatement || context instanceof PsiResource) {
if (context instanceof PsiDeclarationStatement || context instanceof PsiResourceVariable) {
if (!info.isRead()) {
if (!isOnTheFly) {
holder.registerProblem(psiVariable.getNameIdentifier(),
@@ -36,7 +36,7 @@ import static com.intellij.lang.java.parser.JavaParserUtil.exprType;
public class DeclarationParser {
public enum Context {
FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE, RESOURCE_LIST
FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE
}
private static final TokenSet AFTER_END_DECLARATION_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD);
@@ -223,7 +223,7 @@ public class DeclarationParser {
if (tokenType == null) return null;
if (tokenType == JavaTokenType.LBRACE) {
if (context == Context.FILE || context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) return null;
if (context == Context.FILE || context == Context.CODE_BLOCK) return null;
}
else if (tokenType == JavaTokenType.IDENTIFIER || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
if (context == Context.FILE) return null;
@@ -235,7 +235,7 @@ public class DeclarationParser {
else if (!ElementType.MODIFIER_BIT_SET.contains(tokenType) &&
!ElementType.CLASS_KEYWORD_BIT_SET.contains(tokenType) &&
tokenType != JavaTokenType.AT &&
(context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST || tokenType != JavaTokenType.LT)) {
(context == Context.CODE_BLOCK || tokenType != JavaTokenType.LT)) {
return null;
}
@@ -279,7 +279,7 @@ public class DeclarationParser {
final PsiBuilder.Marker idPos = builder.mark();
type = parseTypeNotNull(builder);
if (builder.getTokenType() == JavaTokenType.LPARENTH) { // constructor
if (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) {
if (context == Context.CODE_BLOCK) {
declaration.rollbackTo();
return null;
}
@@ -302,10 +302,6 @@ public class DeclarationParser {
declaration.drop();
return modList;
}
else if (context == Context.RESOURCE_LIST) {
declaration.rollbackTo();
return null;
}
final PsiBuilder.Marker codeBlock = StatementParser.parseCodeBlock(builder);
assert codeBlock != null : builder.getOriginalText();
@@ -331,7 +327,7 @@ public class DeclarationParser {
}
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
if ((context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) && modListInfo.second) {
if ((context == Context.CODE_BLOCK) && modListInfo.second) {
declaration.rollbackTo();
return null;
}
@@ -473,11 +469,11 @@ public class DeclarationParser {
PsiBuilder.Marker invalidElements = null;
String errorMessage = null;
boolean delimiterExpected = false;
int elementCount = 0;
boolean noElements = true;
while (true) {
final IElementType tokenType = builder.getTokenType();
if (tokenType == null || tokenType == JavaTokenType.RPARENTH || tokenType == JavaTokenType.LBRACE) {
boolean noLastElement = !delimiterExpected && elementCount > 0;
final boolean noLastElement = !delimiterExpected && (!noElements && !resources || noElements && resources);
if (noLastElement) {
error(builder, JavaErrorMessages.message("expected.identifier.or.type"));
}
@@ -486,13 +482,10 @@ public class DeclarationParser {
invalidElements.error(errorMessage);
invalidElements = null;
}
else if (resources && elementCount == 0) {
error(builder, JavaErrorMessages.message("expected.resource"));
}
builder.advanceLexer();
}
else {
if (!noLastElement) {
if (!noLastElement || resources) {
if (invalidElements != null) {
invalidElements.error(errorMessage);
}
@@ -522,7 +515,7 @@ public class DeclarationParser {
invalidElements.errorBefore(errorMessage, listElement);
invalidElements = null;
}
elementCount++;
noElements= false;
continue;
}
}
@@ -531,6 +524,9 @@ public class DeclarationParser {
if (builder.getTokenType() == delimiter) {
error(builder, noElementMsg);
builder.advanceLexer();
if (noElements && resources) {
noElements = false;
}
continue;
}
else {
@@ -556,6 +552,19 @@ public class DeclarationParser {
@Nullable
public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) {
return parseListElement(builder, ellipsis, disjunctiveType, false);
}
@Nullable
public static PsiBuilder.Marker parseResource(final PsiBuilder builder) {
return parseListElement(builder, false, false, true);
}
@Nullable
private static PsiBuilder.Marker parseListElement(final PsiBuilder builder,
final boolean ellipsis,
final boolean disjunctiveType,
final boolean resource) {
final PsiBuilder.Marker param = builder.mark();
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
@@ -577,34 +586,26 @@ public class DeclarationParser {
}
if (expect(builder, JavaTokenType.IDENTIFIER)) {
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen"));
done(param, JavaElementType.PARAMETER);
return param;
if (!resource) {
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen"));
done(param, JavaElementType.PARAMETER);
return param;
}
}
else {
error(builder, JavaErrorMessages.message("expected.identifier"));
param.drop();
return modListInfo.first;
}
}
@Nullable
public static PsiBuilder.Marker parseResource(final PsiBuilder builder) {
PsiBuilder.Marker element = parse(builder, Context.RESOURCE_LIST);
if (exprType(element) == JavaElementType.MODIFIER_LIST) {
return element;
}
else if (element == null) {
element = ExpressionParser.parse(builder);
if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) {
if (ExpressionParser.parse(builder) == null) {
error(builder, JavaErrorMessages.message("expected.expression"));
}
}
if (element != null) {
final PsiBuilder.Marker resource = element.precede();
done(resource, JavaElementType.RESOURCE);
return resource;
}
return null;
done(param, JavaElementType.RESOURCE_VARIABLE);
return param;
}
@Nullable
@@ -614,7 +615,7 @@ public class DeclarationParser {
if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) {
varType = JavaElementType.FIELD;
}
else if (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) {
else if (context == Context.CODE_BLOCK) {
varType = JavaElementType.LOCAL_VARIABLE;
}
else {
@@ -645,11 +646,6 @@ public class DeclarationParser {
unclosed = true;
break;
}
if (context == Context.RESOURCE_LIST) break;
}
else if (context == Context.RESOURCE_LIST) {
error(builder, JavaErrorMessages.message("expected.eq"));
break;
}
if (builder.getTokenType() != JavaTokenType.COMMA) break;
@@ -668,28 +664,26 @@ public class DeclarationParser {
builder.advanceLexer();
}
if (context != Context.RESOURCE_LIST) {
if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) {
builder.advanceLexer();
if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) {
builder.advanceLexer();
}
else {
// special treatment (see DeclarationParserTest.testMultiLineUnclosed())
if (!builder.eof() && shouldRollback) {
final CharSequence text = builder.getOriginalText();
final int spaceEnd = builder.getCurrentOffset();
final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES);
final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS);
if (declarationStart < lineStart && lineStart < spaceStart) {
final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES);
declaration.rollbackTo();
return parse(stoppingBuilder(builder, newBufferEnd), context);
}
}
else {
// special treatment (see DeclarationParserTest.testMultiLineUnclosed())
if (!builder.eof() && shouldRollback) {
final CharSequence text = builder.getOriginalText();
final int spaceEnd = builder.getCurrentOffset();
final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES);
final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS);
if (declarationStart < lineStart && lineStart < spaceStart) {
final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES);
declaration.rollbackTo();
return parse(stoppingBuilder(builder, newBufferEnd), context);
}
}
if (!unclosed) {
error(builder, JavaErrorMessages.message("expected.semicolon"));
}
if (!unclosed) {
error(builder, JavaErrorMessages.message("expected.semicolon"));
}
}
@@ -1166,30 +1166,15 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
public void visitResourceList(final PsiResourceList resourceList) {
startElement(resourceList);
final List<PsiResource> resources = resourceList.getResources();
for (PsiResource resource : resources) {
final List<PsiResourceVariable> resources = resourceList.getResourceVariables();
for (PsiResourceVariable resource : resources) {
ProgressManager.checkCanceled();
resource.accept(this);
processVariable(resource);
}
finishElement(resourceList);
}
@Override
public void visitResource(final PsiResource resource) {
startElement(resource);
final PsiElement resourceElement = resource.getResourceElement();
if (resourceElement instanceof PsiLocalVariable) {
processVariable((PsiLocalVariable)resourceElement);
}
else if (resourceElement instanceof PsiExpression) {
resourceElement.accept(this);
}
finishElement(resource);
}
@Override
public void visitWhileStatement(PsiWhileStatement statement) {
startElement(statement);
@@ -230,11 +230,10 @@ public class DefUseUtil {
if (!defsArmed[i]) {
PsiElement context = PsiTreeUtil.getNonStrictParentOfType(flow.getElement(i),
PsiStatement.class, PsiAssignmentExpression.class,
PsiPostfixExpression.class, PsiPrefixExpression.class,
PsiResource.class);
PsiPostfixExpression.class, PsiPrefixExpression.class);
PsiVariable psiVariable = writeInstruction.variable;
if (context != null && !(context instanceof PsiTryStatement)) {
if (isDeclaration(context) && psiVariable.getInitializer() == null) {
if (context instanceof PsiDeclarationStatement && psiVariable.getInitializer() == null) {
if (!assignedVariables.contains(psiVariable)) {
unusedDefs.add(new Info(psiVariable, context, false));
}
@@ -250,11 +249,6 @@ public class DefUseUtil {
return unusedDefs;
}
private static boolean isDeclaration(final PsiElement context) {
return context instanceof PsiDeclarationStatement ||
context instanceof PsiResource && ((PsiResource)context).getResourceElement() instanceof PsiLocalVariable;
}
@NotNull
public static PsiElement[] getDefs(PsiCodeBlock body, final PsiVariable def, PsiElement ref) {
try {
@@ -198,12 +198,9 @@ public class PsiImplUtil {
@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state,
final PsiElement lastParent) {
final List<PsiResource> resources = resourceList.getResources();
for (PsiResource resource : resources) {
final PsiElement resourceElement = resource.getResourceElement();
if (resourceElement instanceof PsiLocalVariable &&
!resourceElement.equals(lastParent) &&
!processor.execute(resourceElement, state)) return false;
final List<PsiResourceVariable> resources = resourceList.getResourceVariables();
for (PsiResourceVariable resource : resources) {
if (!resource.equals(lastParent) && !processor.execute(resource, state)) return false;
}
return true;
@@ -259,13 +259,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
@NotNull
@Override
public PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
public PsiResourceVariable createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiResource)) {
if (!(element instanceof PsiResourceVariable)) {
throw new IncorrectOperationException("Incorrect resource \"" + text + "\".");
}
return (PsiResource)element;
return (PsiResourceVariable)element;
}
@NotNull
@@ -177,9 +177,8 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
else if (parent instanceof PsiParameter) {
if (type == JavaTokenType.FINAL_KEYWORD && ((PsiParameter)parent).getType() instanceof PsiDisjunctionType) return true;
}
else if (parent instanceof PsiLocalVariable) {
PsiElement grandParent = parent.getParent();
if (type == JavaTokenType.FINAL_KEYWORD && grandParent instanceof PsiResource) return true;
else if (parent instanceof PsiResourceVariable) {
if (type == JavaTokenType.FINAL_KEYWORD) return true;
}
if (type == null) { // package local
@@ -128,7 +128,7 @@ public interface JavaElementType {
IElementType SYNCHRONIZED_STATEMENT = new JavaCompositeElementType("SYNCHRONIZED_STATEMENT", PsiSynchronizedStatementImpl.class);
IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class);
IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class);
IElementType RESOURCE = new JavaCompositeElementType("RESOURCE", PsiResourceImpl.class);
IElementType RESOURCE_VARIABLE = new JavaCompositeElementType("RESOURCE_VARIABLE", PsiResourceVariableImpl.class);
IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class);
IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class);
IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class);
@@ -49,13 +49,17 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Set;
public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScopedLocalVariable, PsiVariableEx, Constants {
public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLocalVariable, PsiVariableEx, Constants {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl");
private volatile String myCachedName = null;
public PsiLocalVariableImpl() {
super(LOCAL_VARIABLE);
this(LOCAL_VARIABLE);
}
protected PsiLocalVariableImpl(final IElementType type) {
super(type);
}
public void clearCaches() {
@@ -279,21 +283,6 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScop
return "PsiLocalVariable:" + getName();
}
@NotNull
public PsiElement[] getDeclarationScope() {
final PsiElement parentElement = getParent();
if (parentElement instanceof PsiDeclarationStatement) {
return new PsiElement[]{parentElement.getParent()};
}
else if (parentElement instanceof PsiResource) {
final PsiResourceList resourceList = (PsiResourceList)parentElement.getParent();
final PsiTryStatement tryStatement = (PsiTryStatement)resourceList.getParent();
final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
return tryBlock != null ? new PsiElement[]{resourceList, tryBlock} : new PsiElement[]{resourceList};
}
return new PsiElement[]{parentElement.getParent()};
}
@NotNull
public SearchScope getUseScope() {
if (JspPsiUtil.isInJspFile(this)) {
@@ -321,8 +310,8 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScop
}
final PsiElement parentElement = getParent();
if (parentElement instanceof PsiDeclarationStatement || parentElement instanceof PsiResource) {
return new LocalSearchScope(getDeclarationScope());
if (parentElement instanceof PsiDeclarationStatement) {
return new LocalSearchScope(parentElement.getParent());
}
else {
return getManager().getFileManager().getUseScope(this);
@@ -1,74 +0,0 @@
/*
* Copyright 2000-2011 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiResourceImpl extends CompositePsiElement implements PsiResource {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiResourceImpl");
public PsiResourceImpl() {
super(JavaElementType.RESOURCE);
}
@NotNull
@Override
public PsiElement getResourceElement() {
final PsiElement element = getFirstChild();
assert element != null : this;
return element;
}
@Override
public PsiType getType() {
final PsiElement element = getResourceElement();
if (element instanceof PsiLocalVariable) {
return ((PsiLocalVariable)element).getType();
}
else if (element instanceof PsiExpression) {
return ((PsiExpression)element).getType();
}
LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element));
return null;
}
@Override
public void accept(@NotNull final PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitResource(this);
}
else {
visitor.visitElement(this);
}
}
public String getName() {
final PsiElement element = getFirstChild();
if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getName();
if (element instanceof PsiAssignmentExpression) return ((PsiAssignmentExpression)element).getLExpression().toString();
return "";
}
@Override
public String toString() {
return "PsiResource:" + getName();
}
}
@@ -32,8 +32,8 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou
@NotNull
@Override
public List<PsiResource> getResources() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiResource.class);
public List<PsiResourceVariable> getResourceVariables() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiResourceVariable.class);
}
@Override
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2011 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
public class PsiResourceVariableImpl extends PsiLocalVariableImpl implements PsiResourceVariable {
public PsiResourceVariableImpl() {
super(JavaElementType.RESOURCE_VARIABLE);
}
@NotNull
@Override
public PsiElement[] getDeclarationScope() {
final PsiResourceList resourceList = (PsiResourceList)getParent();
final PsiTryStatement tryStatement = (PsiTryStatement)resourceList.getParent();
final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
return tryBlock != null ? new PsiElement[]{resourceList, tryBlock} : new PsiElement[]{resourceList};
}
@NotNull
@Override
public PsiTypeElement getTypeElement() {
return PsiTreeUtil.getRequiredChildOfType(this, PsiTypeElement.class);
}
@Override
public PsiModifierList getModifierList() {
return PsiTreeUtil.getChildOfType(this, PsiModifierList.class);
}
@Override
public void accept(@NotNull final PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitResourceVariable(this);
}
else {
visitor.visitElement(this);
}
}
@NotNull
@Override
public SearchScope getUseScope() {
return new LocalSearchScope(getDeclarationScope());
}
@Override
public String toString() {
return "PsiResourceVariable:" + getName();
}
}
@@ -14,24 +14,22 @@ class C {
try (MyResource r = new MyResource()) { r.doSomething(); }
catch (E1 | E2 | E3 ignore) { }
try (new MyResource()) { }
try (MyResource r = new MyResource()) { }
catch (E1 | E3 ignore) { }
MyResource r;
try (<error descr="Unhandled exception from auto-closeable resource: C.E3">r = new MyResource()</error>) { }
try (<error descr="Unhandled exception from auto-closeable resource: C.E3">MyResource r = new MyResource()</error>) { }
catch (E1 e) { }
try (r = <error descr="Unhandled exception: C.E1">new MyResource()</error>) { }
try (MyResource r = <error descr="Unhandled exception: C.E1">new MyResource()</error>) { }
catch (E3 e) { }
try (r = <error descr="Unhandled exception: C.E1">new MyResource()</error>) { }
try (MyResource r = <error descr="Unhandled exception: C.E1">new MyResource()</error>) { }
}
void m2() throws Exception {
try (<error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.AutoCloseable'">Object r = new MyResource()</error>) { }
try (<error descr="Incompatible types. Found: 'java.lang.String', required: 'java.lang.AutoCloseable'">"resource"</error>) { }
try (<error descr="Incompatible types. Found: 'java.lang.String', required: 'java.lang.AutoCloseable'">AutoCloseable r = "resource"</error>) { }
}
void m3(int p) throws Exception {
@@ -56,7 +54,7 @@ class C {
MyResource r = null;
try (MyResource <error descr="Variable 'r' is already defined in the scope">r</error> = new MyResource()) { }
try (r = new MyResource()) { }
try (MyResource rr = r) { }
try (MyResource <error descr="Variable 'p' is already defined in the scope">p</error> = new MyResource()) { }
new Runnable() {
@@ -6,35 +6,28 @@ class C {
}
void m1() throws Exception {
MyResource r1;
try (r1 = new MyResource()) {
try (MyResource r1 = new MyResource()) {
System.out.println(r1);
}
try (MyResource r2 = new MyResource()) {
System.out.println(r2);
}
MyResource r3 = new MyResource();
try (MyResource r = r3) {
MyResource r2 = new MyResource();
try (MyResource r = r2) {
System.out.println(r);
System.out.println(r2);
}
}
void m2() throws Exception {
MyResource r1 = <warning descr="Variable 'r1' initializer 'null' is redundant">null</warning>;
try (r1 = new MyResource()) {
System.out.println(r1);
}
// todo: test in IG
//MyResource < warning descr="Local variable 'r1' is redundant">r1</warning> = null;
//try (MyResource r = r1) {
// System.out.println(r);
//}
MyResource r2 = null;
System.out.println(r2);
try (r2 = <warning descr="The value 'new MyResource()' assigned to r2 is never used">new MyResource()</warning>) { }
try (MyResource <warning descr="Variable 'r2' is never used">r2</warning> = new MyResource()) { }
try (MyResource <warning descr="Variable 'r3' is never used">r3</warning> = new MyResource()) { }
MyResource <warning descr="Variable 'r4' is never assigned">r4</warning>;
try (MyResource r = <error descr="Variable 'r4' might not have been initialized">r4</error>) {
MyResource <warning descr="Variable 'r3' is never assigned">r3</warning>;
try (MyResource r = <error descr="Variable 'r3' might not have been initialized">r3</error>) {
System.out.println(r);
}
}
@@ -3,6 +3,8 @@ PsiJavaFile:TryIncomplete10.java
PsiKeyword:try('try')
PsiResourceList:(
PsiJavaToken:LPARENTH('(')
PsiErrorElement:Identifier or type expected
<empty list>
PsiErrorElement:')' expected
<empty list>
PsiCodeBlock
@@ -3,7 +3,7 @@ PsiJavaFile:TryIncomplete11.java
PsiKeyword:try('try')
PsiResourceList:()
PsiJavaToken:LPARENTH('(')
PsiErrorElement:Resource definition expected
PsiErrorElement:Identifier or type expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
@@ -6,8 +6,6 @@ PsiJavaFile:TryIncomplete12.java
PsiErrorElement:Resource definition expected
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiErrorElement:Resource definition expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
@@ -5,9 +5,13 @@ PsiJavaFile:TryIncomplete13.java
PsiJavaToken:LPARENTH('(')
PsiModifierList:final
PsiKeyword:final('final')
PsiErrorElement:Identifier or type expected
PsiErrorElement:Type expected
<empty list>
PsiWhiteSpace(' ')
PsiTypeElement:
<empty list>
PsiErrorElement:Identifier expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
@@ -3,8 +3,12 @@ PsiJavaFile:TryIncomplete14.java
PsiKeyword:try('try')
PsiResourceList:(int)
PsiJavaToken:LPARENTH('(')
PsiErrorElement:Resource definition expected
PsiModifierList:
<empty list>
PsiTypeElement:int
PsiKeyword:int('int')
PsiErrorElement:Identifier expected
<empty list>
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
@@ -3,19 +3,18 @@ PsiJavaFile:TryIncomplete15.java
PsiKeyword:try('try')
PsiResourceList:(R r)
PsiJavaToken:LPARENTH('(')
PsiResource:r
PsiLocalVariable:r
PsiModifierList:
<empty list>
PsiTypeElement:R
PsiJavaCodeReferenceElement:R
PsiIdentifier:R('R')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiIdentifier:r('r')
PsiErrorElement:'=' expected
<empty list>
PsiResourceVariable: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('{')
@@ -3,21 +3,20 @@ PsiJavaFile:TryIncomplete16.java
PsiKeyword:try('try')
PsiResourceList:(R r =)
PsiJavaToken:LPARENTH('(')
PsiResource:r
PsiLocalVariable: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>
PsiResourceVariable: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('{')
@@ -1,27 +1,27 @@
PsiJavaFile:TryIncomplete17.java
PsiTryStatement
PsiKeyword:try('try')
PsiResourceList:(R r = 0;)
PsiResourceList:(R r = 0;;)
PsiJavaToken:LPARENTH('(')
PsiResource:r
PsiLocalVariable: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')
PsiResourceVariable: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
PsiErrorElement:Resource definition expected
<empty list>
PsiJavaToken:SEMICOLON(';')
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
@@ -3,22 +3,21 @@ PsiJavaFile:TryNormal4.java
PsiKeyword:try('try')
PsiResourceList:(R r = 0)
PsiJavaToken:LPARENTH('(')
PsiResource:r
PsiLocalVariable: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')
PsiResourceVariable: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('{')
@@ -3,40 +3,38 @@ PsiJavaFile:TryNormal5.java
PsiKeyword:try('try')
PsiResourceList:(R1 r1 = 1; R2 r2 = 2)
PsiJavaToken:LPARENTH('(')
PsiResource:r1
PsiLocalVariable: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')
PsiResourceVariable: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(' ')
PsiResource:r2
PsiLocalVariable: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')
PsiResourceVariable: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('{')
@@ -1,13 +1,24 @@
PsiJavaFile:TryNormal6.java
PsiTryStatement
PsiKeyword:try('try')
PsiResourceList:(r)
PsiResourceList:(R r = 0;)
PsiJavaToken:LPARENTH('(')
PsiResource:
PsiReferenceExpression:r
PsiReferenceParameterList
<empty list>
PsiIdentifier:r('r')
PsiResourceVariable: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(';')
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
@@ -1,19 +0,0 @@
PsiJavaFile:TryNormal7.java
PsiTryStatement
PsiKeyword:try('try')
PsiResourceList:(r; null)
PsiJavaToken:LPARENTH('(')
PsiResource:
PsiReferenceExpression:r
PsiReferenceParameterList
<empty list>
PsiIdentifier:r('r')
PsiJavaToken:SEMICOLON(';')
PsiWhiteSpace(' ')
PsiResource:
PsiLiteralExpression:null
PsiJavaToken:NULL_KEYWORD('null')
PsiJavaToken:RPARENTH(')')
PsiCodeBlock
PsiJavaToken:LBRACE('{')
PsiJavaToken:RBRACE('}')
@@ -32,7 +32,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{new UnusedSymbolLocalInspection(), new UncheckedWarningLocalInspection(), new DefUseInspection()};
return new LocalInspectionTool[]{new UnusedSymbolLocalInspection(), new UncheckedWarningLocalInspection()};
}
public void testDuplicateAnnotations() throws Exception {
@@ -194,6 +194,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
}
public void testTryWithResourcesWarn() throws Exception {
enableInspectionTool(new DefUseInspection());
doTest(true, false);
}
@@ -122,8 +122,7 @@ public class StatementParserTest extends JavaParsingTestCase {
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 testTryNormal6() { doParserTestJDK7("try(r){}"); }
public void testTryNormal7() { doParserTestJDK7("try(r; null){}"); }
public void testTryNormal6() { doParserTestJDK7("try(R r = 0;){}"); }
public void testTryIncomplete0() { doParserTest("try"); }
public void testTryIncomplete1() { doParserTest("try{}"); }
public void testTryIncomplete2() { doParserTest("try{}catch"); }
@@ -141,7 +140,7 @@ public class StatementParserTest extends JavaParsingTestCase {
public void testTryIncomplete14() { doParserTestJDK7("try(int){}"); }
public void testTryIncomplete15() { doParserTestJDK7("try(R r){}"); }
public void testTryIncomplete16() { doParserTestJDK7("try(R r =){}"); }
public void testTryIncomplete17() { doParserTestJDK7("try(R r = 0;){}"); }
public void testTryIncomplete17() { doParserTestJDK7("try(R r = 0;;){}"); }
public void testWhileNormal() { doParserTest("while (true) foo();"); }
public void testWhileIncomplete0() { doParserTest("while"); }
@@ -300,8 +300,8 @@ public abstract class JavaElementVisitor extends PsiElementVisitor {
visitElement(resourceList);
}
public void visitResource(PsiResource resource) {
visitElement(resource);
public void visitResourceVariable(PsiResourceVariable resourceVariable) {
visitLocalVariable(resourceVariable);
}
public void visitTypeElement(PsiTypeElement type) {
@@ -125,7 +125,7 @@ public interface PsiJavaParserFacade extends PsiParserFacade {
* @throws com.intellij.util.IncorrectOperationException if the text is not a valid resource definition.
*/
@NotNull
PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException;
PsiResourceVariable createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException;
/**
* Creates a Java type from the specified text.
@@ -1,39 +0,0 @@
/*
* Copyright 2000-2011 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a resource list of try-with-resources statement (automatic resource management) introduced in JDK 7.
*
* @see PsiResourceList#getResources()
* @since 10.5.
*/
public interface PsiResource extends PsiElement {
/**
* Returns main element of the resource.
* It may be PsiLocalVariable, PsiAssignmentExpression, or other instance of PsiExpression.
*
* @return resource element.
*/
@NotNull
PsiElement getResourceElement();
@Nullable
PsiType getType();
}
@@ -27,5 +27,5 @@ import java.util.List;
*/
public interface PsiResourceList extends PsiElement {
@NotNull
List<PsiResource> getResources();
List<PsiResourceVariable> getResourceVariables();
}
@@ -17,12 +17,13 @@ package com.intellij.psi;
import org.jetbrains.annotations.NotNull;
public interface PsiScopedLocalVariable extends PsiLocalVariable {
/**
* Returns the element or elements (method, "for" statement or try block) in which the variable is declared.
*
* @return the declaration scope for the variable.
*/
/**
* Represents a resource variable of try-with-resources statement (automatic resource management) introduced in JDK 7.
*
* @see PsiResourceList#getResourceVariables()
* @since 10.5.
*/
public interface PsiResourceVariable extends PsiLocalVariable {
@NotNull
PsiElement[] getDeclarationScope();
}