summaryrefslogtreecommitdiff
path: root/java/java-psi-impl/src/com/intellij/psi/impl/source
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-07-08 11:26:24 -0700
committerTor Norbye <tnorbye@google.com>2013-07-08 11:26:24 -0700
commitc1ace1f7e1e49c81bb4b75377c99f07be340abfe (patch)
tree9d0db96bd3d86ddfec80e7e3554cad9dcc066553 /java/java-psi-impl/src/com/intellij/psi/impl/source
parentc6218e46d5d2017e987ecdbd99b318a95c42abc0 (diff)
downloadidea-c1ace1f7e1e49c81bb4b75377c99f07be340abfe.tar.gz
Snapshot aea001abfc1b38fec3a821bcd5174cc77dc75787 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: Icdea2a2bd7ad43b4d05967b1f0479db3bda1c93c
Diffstat (limited to 'java/java-psi-impl/src/com/intellij/psi/impl/source')
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java7
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java8
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java96
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java1
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java52
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java1
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java20
9 files changed, 169 insertions, 25 deletions
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
index 348f6ba44a28..72cd0de14559 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -32,8 +31,7 @@ import java.util.List;
* @author max
*/
public class PsiClassReferenceType extends PsiClassType {
- private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiClassReferenceType");
-
+ @NotNull
private final PsiJavaCodeReferenceElement myReference;
public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) {
@@ -173,10 +171,11 @@ public class PsiClassReferenceType extends PsiClassType {
return myReference.getTypeParameters();
}
+ @NotNull
public PsiClassType createImmediateCopy() {
ClassResolveResult resolveResult = resolveGenerics();
PsiClass element = resolveResult.getElement();
- return element != null ? new PsiImmediateClassType(element, resolveResult.getSubstitutor()) : this;
+ return element == null ? this : new PsiImmediateClassType(element, resolveResult.getSubstitutor());
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
index e71bf636fa02..47a1b8e3f159 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java
@@ -142,7 +142,9 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
StubElement<?> stub = getStub();
if (stub != null) {
PsiImportList[] nodes = stub.getChildrenByType(JavaStubElementTypes.IMPORT_LIST, PsiImportList.ARRAY_FACTORY);
- assert nodes.length == 1 : stub + "; " + stub.getChildrenStubs();
+ if (nodes.length != 1) {
+ reportStubAstMismatch(stub + "; " + stub.getChildrenStubs(), getStubTree(), PsiDocumentManager.getInstance(getProject()).getCachedDocument(this));
+ }
return nodes[0];
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
index ec4cec31578a..bafbd37eac87 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
@@ -159,7 +159,13 @@ public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> imple
@Override
public PsiTypeElement getTypeElement() {
- return PsiTreeUtil.getChildOfType(this, PsiTypeElement.class);
+ for (PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child instanceof PsiTypeElement) {
+ //noinspection unchecked
+ return (PsiTypeElement)child;
+ }
+ }
+ return null;
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java
new file mode 100644
index 000000000000..221f48238c8e
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/InferenceGraphNode.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ * 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.resolve;
+
+import com.intellij.psi.PsiTypeParameter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * User: anna
+ * Date: 7/4/13
+ */
+public class InferenceGraphNode<T> {
+ private final T myValue;
+ private final List<InferenceGraphNode<T>> myDependencies = new ArrayList<InferenceGraphNode<T>>();
+
+ private int index = -1;
+ private int lowlink;
+
+ public InferenceGraphNode(T value) {
+ myValue = value;
+ }
+
+ public T getValue() {
+ return myValue;
+ }
+
+ public List<InferenceGraphNode<T>> getDependencies() {
+ return myDependencies;
+ }
+
+ public void addDependency(InferenceGraphNode<T> node) {
+ myDependencies.add(node);
+ }
+
+ public static <T> List<List<InferenceGraphNode<T>>> tarjan(Collection<InferenceGraphNode<T>> nodes) {
+ final ArrayList<List<InferenceGraphNode<T>>> result = new ArrayList<List<InferenceGraphNode<T>>>();
+ final Stack<InferenceGraphNode<T>> currentStack = new Stack<InferenceGraphNode<T>>();
+ int index = 0;
+ for (InferenceGraphNode<T> node : nodes) {
+ if (node.index == -1) {
+ index += strongConnect(node, index, currentStack, result);
+ }
+ }
+ return result;
+ }
+
+ private static <T> int strongConnect(InferenceGraphNode<T> currentNode,
+ int index,
+ Stack<InferenceGraphNode<T>> currentStack,
+ ArrayList<List<InferenceGraphNode<T>>> result) {
+ currentNode.index = index;
+ currentNode.lowlink = index;
+ index++;
+
+ currentStack.push(currentNode);
+
+ for (InferenceGraphNode<T> dependantNode : currentNode.getDependencies()) {
+ if (dependantNode.index == -1) {
+ strongConnect(dependantNode, index, currentStack, result);
+ currentNode.lowlink = Math.min(currentNode.lowlink, dependantNode.lowlink);
+ }
+ else if (currentStack.contains(dependantNode)) {
+ currentNode.lowlink = Math.min(currentNode.lowlink, dependantNode.index);
+ }
+ }
+
+ if (currentNode.lowlink == currentNode.index) {
+ final ArrayList<InferenceGraphNode<T>> arrayList = new ArrayList<InferenceGraphNode<T>>();
+ InferenceGraphNode<T> cyclicNode;
+ do {
+ cyclicNode = currentStack.pop();
+ arrayList.add(cyclicNode);
+ }
+ while (cyclicNode != currentNode);
+ result.add(arrayList);
+ }
+ return index;
+ }
+}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
index d17355fdc916..73895177261c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
@@ -32,7 +32,6 @@ import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.reference.SoftReference;
-import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.messages.MessageBus;
@@ -96,10 +95,8 @@ public class JavaResolveCache {
}
if (type == null) type = TypeConversionUtil.NULL_TYPE;
Reference<PsiType> ref = new SoftReference<PsiType>(type);
- Reference<PsiType> storedRef = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, expr, ref);
+ myCalculatedTypes.put(expr, ref);
- PsiType stored = ref == storedRef ? type : storedRef.get();
- type = stored == null ? type : stored;
if (type instanceof PsiClassReferenceType) {
// convert reference-based class type to the PsiImmediateClassType, since the reference may become invalid
PsiClassType.ClassResolveResult result = ((PsiClassReferenceType)type).resolveGenerics();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
index 60be7ada6585..6dd543993fb6 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java
@@ -361,6 +361,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
@SuppressWarnings("unchecked")
Pair<PsiType, ConstraintType>[] constraints = new Pair[typeParameters.length];
PsiFile file = parent.getContainingFile();
+ LOG.assertTrue(file != null, parent);
final PsiManager manager = file.getManager();
final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(file);
for (int i = 0; i < typeParameters.length; i++) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
index 550da84ec9e9..4b2dc0b96d3d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
@@ -46,15 +46,14 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.CharTable;
-import com.intellij.util.Function;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.NullableFunction;
+import com.intellij.util.*;
+import com.intellij.util.containers.Stack;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -185,6 +184,14 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
private static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver<PsiJavaReference> {
private static final OurGenericsResolver INSTANCE = new OurGenericsResolver();
+ @SuppressWarnings("SSBasedInspection")
+ private static final ThreadLocal<Stack<Object>> ourQualifiers = new ThreadLocal<Stack<Object>>() {
+ @Override
+ protected Stack<Object> initialValue() {
+ return new Stack<Object>();
+ }
+ };
+
@Override
@NotNull
public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) {
@@ -192,29 +199,43 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
CompositeElement treeParent = expression.getTreeParent();
IElementType parentType = treeParent == null ? null : treeParent.getElementType();
PsiFile file = expression.getContainingFile();
- resolveAllQualifiers(expression, file);
- JavaResolveResult[] result = expression.resolve(parentType, file);
- if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) {
- result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, file);
- }
+ List<ResolveResult[]> qualifierResults = resolveAllQualifiers(expression, file);
+ ourQualifiers.get().push(qualifierResults);
+ try {
+ JavaResolveResult[] result = expression.resolve(parentType, file);
- JavaResolveUtil.substituteResults(expression, result);
+ if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) {
+ result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION, file);
+ }
- return result;
+ JavaResolveUtil.substituteResults(expression, result);
+
+ return result;
+ }
+ finally {
+ ourQualifiers.get().pop();
+ }
}
- private static void resolveAllQualifiers(@NotNull PsiReferenceExpressionImpl expression, final PsiFile containingFile) {
+ private static List<ResolveResult[]> resolveAllQualifiers(@NotNull PsiReferenceExpressionImpl expression, final PsiFile containingFile) {
// to avoid SOE, resolve all qualifiers starting from the innermost
PsiElement qualifier = expression.getQualifier();
- if (qualifier == null) return;
+ if (qualifier == null) return Collections.emptyList();
+
+ final List<ResolveResult[]> qualifierResults = new SmartList<ResolveResult[]>();
final ResolveCache resolveCache = ResolveCache.getInstance(containingFile.getProject());
qualifier.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
- if (!(expression instanceof PsiReferenceExpressionImpl) || resolveCache.isCached(expression, true, false, true)) {
+ if (!(expression instanceof PsiReferenceExpressionImpl)) {
+ return;
+ }
+ ResolveResult[] cachedResults = resolveCache.getCachedResults(expression, true, false, true);
+ if (cachedResults == null) {
return;
}
+ qualifierResults.add(cachedResults);
visitElement(expression);
}
@@ -222,9 +243,10 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
protected void elementFinished(PsiElement element) {
if (!(element instanceof PsiReferenceExpressionImpl)) return;
PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)element;
- resolveCache.resolveWithCaching(expression, INSTANCE, false, false, containingFile);
+ qualifierResults.add(resolveCache.resolveWithCaching(expression, INSTANCE, false, false, containingFile));
}
});
+ return qualifierResults;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java
index fcc7d7eb12b2..3f0878c3a18c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java
@@ -68,6 +68,7 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou
public void deleteChildInternal(@NotNull final ASTNode child) {
if (child.getPsi() instanceof PsiResourceVariable && getResourceVariablesCount() == 1) {
getTreeParent().deleteChildInternal(this);
+ return;
}
super.deleteChildInternal(child);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java
index 3eefe9108c91..5af48582a637 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java
@@ -181,6 +181,26 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt
return true;
}
+ @Override
+ public void deleteChildInternal(@NotNull ASTNode child) {
+ if (child.getPsi() instanceof PsiResourceList && getCatchBlocks().length == 0 && getFinallyBlock() == null) {
+ final PsiCodeBlock tryBlock = getTryBlock();
+ if (tryBlock != null) {
+ final PsiCodeBlock block = (PsiCodeBlock)replace(tryBlock);
+ final PsiJavaToken lBrace = block.getLBrace();
+ final PsiJavaToken rBrace = block.getRBrace();
+ if (lBrace != null) {
+ lBrace.delete();
+ }
+ if (rBrace != null) {
+ rBrace.delete();
+ }
+ return;
+ }
+ }
+ super.deleteChildInternal(child);
+ }
+
public String toString() {
return "PsiTryStatement";
}