/* * 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.graphInference; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.impl.light.LightTypeParameter; import java.util.*; /** * User: anna */ public class InferenceVariable extends LightTypeParameter { private PsiElement myContext; public PsiTypeParameter getParameter() { return getDelegate(); } private boolean myThrownBound = false; private final Map> myBounds = new HashMap>(); private PsiType myInstantiation = PsiType.NULL; InferenceVariable(PsiElement context, PsiTypeParameter parameter) { super(parameter); myContext = context; } public PsiType getInstantiation() { return myInstantiation; } public void setInstantiation(PsiType instantiation) { myInstantiation = instantiation; } public boolean addBound(PsiType classType, InferenceBound inferenceBound) { List list = myBounds.get(inferenceBound); if (list == null) { list = new ArrayList(); myBounds.put(inferenceBound, list); } final int idx = list.indexOf(classType); if (idx < 0) { list.add(classType); return true; } return false; } public List getBounds(InferenceBound inferenceBound) { final List bounds = myBounds.get(inferenceBound); return bounds != null ? new ArrayList(bounds) : Collections.emptyList(); } public Set getDependencies(InferenceSession session) { final Set dependencies = new LinkedHashSet(); for (List boundTypes : myBounds.values()) { if (boundTypes != null) { for (PsiType bound : boundTypes) { session.collectDependencies(bound, dependencies); } } } next: for (InferenceVariable variable : session.getInferenceVariables()) { if (!dependencies.contains(variable) && variable != this) { nextBound: for (List bounds : myBounds.values()) { //todo if (bounds != null) { for (PsiType bound : bounds) { final Set deps = new HashSet(); session.collectDependencies(bound, deps); if (deps.isEmpty()) { continue nextBound; } if (deps.contains(this)) { dependencies.add(variable); continue next; } } } } } } if (!session.hasCapture(this)) { return dependencies; } for (Iterator iterator = dependencies.iterator(); iterator.hasNext(); ) { if (!session.hasCapture(iterator.next())) { iterator.remove(); } } session.collectCaptureDependencies(this, dependencies); return dependencies; } public boolean hasInstantiation(InferenceSession session) { List bounds = getBounds(InferenceBound.EQ); if (bounds != null) { for (PsiType bound : bounds) { if (session.isProperType(bound)) return true; } } return false; } public boolean isThrownBound() { return myThrownBound; } public void setThrownBound() { myThrownBound = true; } @Override public boolean isEquivalentTo(PsiElement another) { return this == another || getDelegate() == another; } @Override public String toString() { return getDelegate().toString(); } public PsiElement getCallContext() { return myContext; } }