diff options
author | Tor Norbye <tnorbye@google.com> | 2013-07-08 11:26:24 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2013-07-08 11:26:24 -0700 |
commit | c1ace1f7e1e49c81bb4b75377c99f07be340abfe (patch) | |
tree | 9d0db96bd3d86ddfec80e7e3554cad9dcc066553 /java/java-psi-impl/src/com/intellij/psi/impl/source | |
parent | c6218e46d5d2017e987ecdbd99b318a95c42abc0 (diff) | |
download | idea-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')
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"; } |