rename: remember 'Search for text occurrences' checkbox state (IDEA-21328)
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / ExpectedTypeUtil.java
blobe2adbbc9e844af58c0cc1c45062ef8f51aed808f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.codeInsight;
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.psi.*;
20 import com.intellij.psi.util.PsiUtil;
21 import org.jetbrains.annotations.Nullable;
23 import java.util.*;
25 public class ExpectedTypeUtil {
26 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ExpectedTypeUtil");
28 public static ExpectedTypeInfo[] intersect(List<ExpectedTypeInfo[]> typeInfos) {
29 if (typeInfos.isEmpty()) return ExpectedTypeInfo.EMPTY_ARRAY;
31 ExpectedTypeInfos result = new ExpectedTypeInfos(typeInfos.get(0));
32 ExpectedTypeInfos acc = new ExpectedTypeInfos();
34 for (int i = 1; i < typeInfos.size(); i++) {
35 ExpectedTypeInfo[] next = typeInfos.get(i);
36 acc.clear();
37 for (ExpectedTypeInfo info : next) {
38 for (Iterator<ExpectedTypeInfo> iterator = result.iterator(); iterator.hasNext();) {
39 ExpectedTypeInfo[] intersection = iterator.next().intersect(info);
40 for (ExpectedTypeInfo aIntersection : intersection) {
41 acc.addInfo(aIntersection);
45 if (acc.isEmpty()) {
46 return ExpectedTypeInfo.EMPTY_ARRAY;
48 result = acc;
51 return result.toArray();
54 private static class ExpectedTypeInfos {
55 List<ExpectedTypeInfo> myInfos;
57 public ExpectedTypeInfos() {
58 myInfos = new ArrayList<ExpectedTypeInfo>();
61 public ExpectedTypeInfos(ExpectedTypeInfo[] infos) {
62 myInfos = new ArrayList<ExpectedTypeInfo>(Arrays.asList(infos));
65 public void clear () { myInfos.clear(); }
67 public void addInfo (ExpectedTypeInfo info) {
68 for (Iterator<ExpectedTypeInfo> iterator = myInfos.iterator(); iterator.hasNext();) {
69 ExpectedTypeInfo sub = iterator.next();
70 int cmp = contains(sub, info);
71 if (cmp > 0) return;
72 else if (cmp < 0) {
73 iterator.remove();
76 myInfos.add(info);
79 public boolean isEmpty() {
80 return myInfos.isEmpty();
83 public Iterator<ExpectedTypeInfo> iterator() {
84 return myInfos.iterator();
87 public ExpectedTypeInfo[] toArray() {
88 return myInfos.toArray(new ExpectedTypeInfo[myInfos.size()]);
92 /**
93 * @return <0 if info2 contains info1 (or they are equal)
94 * >0 if info1 contains info2
95 * 0 otherwise
97 public static int contains(ExpectedTypeInfo info1, ExpectedTypeInfo info2) {
98 int kind1 = info1.getKind();
99 int kind2 = info2.getKind();
100 if (kind1 == kind2) {
101 if (matchesStrictly(info1.getType(), info2)) return -1;
102 if (matchesStrictly(info2.getType(), info1)) return 1;
103 return 0;
104 } else if (kind1 == ExpectedTypeInfo.TYPE_STRICTLY) {
105 return matches(info1.getType(), info2) ? -1 : 0;
106 } else if (kind2 == ExpectedTypeInfo.TYPE_STRICTLY) {
107 return matches(info2.getType(), info1) ? 1 : 0;
109 return 0;
112 private static boolean matchesStrictly (PsiType type, ExpectedTypeInfo info) {
113 if ((type instanceof PsiPrimitiveType) != (info.getType() instanceof PsiPrimitiveType)) return false;
114 return matches(type, info);
117 public static boolean matches (PsiType type, ExpectedTypeInfo info) {
118 PsiType infoType = info.getType();
119 switch (info.getKind()) {
120 case ExpectedTypeInfo.TYPE_STRICTLY:
121 return type.equals(infoType);
122 case ExpectedTypeInfo.TYPE_OR_SUBTYPE:
123 return infoType.isAssignableFrom(type);
124 case ExpectedTypeInfo.TYPE_OR_SUPERTYPE:
125 return type.isAssignableFrom(infoType);
128 LOG.error("Unexpected ExpectedInfo kind");
129 return false;
132 public static class ExpectedClassesFromSetProvider implements ExpectedTypesProvider.ExpectedClassProvider {
133 private final Set<PsiClass> myOccurrenceClasses;
135 public ExpectedClassesFromSetProvider(Set<PsiClass> occurrenceClasses) {
136 myOccurrenceClasses = occurrenceClasses;
139 public PsiField[] findDeclaredFields(final PsiManager manager, String name) {
140 List<PsiField> fields = new ArrayList<PsiField>();
141 for (PsiClass aClass : myOccurrenceClasses) {
142 final PsiField field = aClass.findFieldByName(name, true);
143 if (field != null) fields.add(field);
145 return fields.toArray(new PsiField[fields.size()]);
148 public PsiMethod[] findDeclaredMethods(final PsiManager manager, String name) {
149 List<PsiMethod> methods = new ArrayList<PsiMethod>();
150 for (PsiClass aClass : myOccurrenceClasses) {
151 final PsiMethod[] occMethod = aClass.findMethodsByName(name, true);
152 methods.addAll(Arrays.asList(occMethod));
154 return methods.toArray(new PsiMethod[methods.size()]);
158 @Nullable
159 public static PsiSubstitutor inferSubstitutor(final PsiMethod method, final PsiMethodCallExpression callExpr, final boolean forCompletion) {
160 final PsiResolveHelper helper = JavaPsiFacade.getInstance(method.getProject()).getResolveHelper();
161 final PsiParameter[] parameters = method.getParameterList().getParameters();
162 PsiExpression[] args = callExpr.getArgumentList().getExpressions();
163 PsiSubstitutor result = PsiSubstitutor.EMPTY;
164 for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(method.getContainingClass())) {
165 PsiType type = helper.inferTypeForMethodTypeParameter(typeParameter, parameters, args, PsiSubstitutor.EMPTY, callExpr.getParent(), forCompletion);
166 if (PsiType.NULL.equals(type)) return null;
167 result = result.put(typeParameter, type);
170 return result;