private static PsiSubstitutor obtainFinalSubstitutor(
      PsiClass superClass,
      PsiSubstitutor superSubstitutor,
      PsiSubstitutor derivedSubstitutor,
      boolean inRawContext) {
    if (inRawContext) {
      Set<PsiTypeParameter> typeParams = superSubstitutor.getSubstitutionMap().keySet();
      PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject());
      superSubstitutor =
          factory.createRawSubstitutor(
              derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()]));
    }
    Map<PsiTypeParameter, PsiType> map = null;
    for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) {
      PsiType type = superSubstitutor.substitute(typeParameter);
      final PsiType t = derivedSubstitutor.substitute(type);
      if (map == null) {
        map = new THashMap<PsiTypeParameter, PsiType>();
      }
      map.put(typeParameter, t);
    }

    return map == null
        ? PsiSubstitutor.EMPTY
        : JavaPsiFacade.getInstance(superClass.getProject())
            .getElementFactory()
            .createSubstitutor(map);
  }
  /* Guesswork
   */
  @Nullable
  private static PsiSubstitutor getInheritorSubstitutorForNewExpression(
      final PsiClass baseClass,
      final PsiClass inheritor,
      final PsiSubstitutor baseSubstitutor,
      final PsiElement context) {
    final Project project = baseClass.getProject();
    JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    final PsiResolveHelper resolveHelper = facade.getResolveHelper();
    PsiSubstitutor superSubstitutor =
        TypeConversionUtil.getClassSubstitutor(baseClass, inheritor, PsiSubstitutor.EMPTY);
    if (superSubstitutor == null) return null;
    PsiSubstitutor inheritorSubstitutor = PsiSubstitutor.EMPTY;
    for (PsiTypeParameter inheritorParameter : PsiUtil.typeParametersIterable(inheritor)) {
      for (PsiTypeParameter baseParameter : PsiUtil.typeParametersIterable(baseClass)) {
        final PsiType substituted = superSubstitutor.substitute(baseParameter);
        PsiType arg = baseSubstitutor.substitute(baseParameter);
        if (arg instanceof PsiWildcardType) arg = ((PsiWildcardType) arg).getBound();
        PsiType substitution =
            resolveHelper.getSubstitutionForTypeParameter(
                inheritorParameter, substituted, arg, true, PsiUtil.getLanguageLevel(context));
        if (PsiType.NULL.equals(substitution)) continue;
        if (substitution == null) {
          return facade.getElementFactory().createRawSubstitutor(inheritor);
        }
        inheritorSubstitutor = inheritorSubstitutor.put(inheritorParameter, substitution);
        break;
      }
    }

    return inheritorSubstitutor;
  }
  private Binding unify(final PsiType x, final PsiType y, final Unifier unifier) {
    final int indicator =
        (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0);

    switch (indicator) {
      case 0:
        if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
          return unifier.unify(x, y);
        } else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
          final PsiType xType =
              x instanceof PsiArrayType ? ((PsiArrayType) x).getComponentType() : x;
          final PsiType yType =
              y instanceof PsiArrayType ? ((PsiArrayType) y).getComponentType() : y;

          return unify(xType, yType, unifier);
        } else if (x instanceof PsiClassType && y instanceof PsiClassType) {
          final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
          final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);

          final PsiClass xClass = resultX.getElement();
          final PsiClass yClass = resultY.getElement();

          if (xClass != null && yClass != null) {
            final PsiSubstitutor ySubst = resultY.getSubstitutor();

            final PsiSubstitutor xSubst = resultX.getSubstitutor();

            if (!xClass.equals(yClass)) {
              return null;
            }

            Binding b = create();

            for (final PsiTypeParameter aParm : xSubst.getSubstitutionMap().keySet()) {
              final PsiType xType = xSubst.substitute(aParm);
              final PsiType yType = ySubst.substitute(aParm);

              final Binding b1 = unify(xType, yType, unifier);

              if (b1 == null) {
                return null;
              }

              b = b.compose(b1);
            }

            return b;
          }
        } else if (y instanceof Bottom) {
          return create();
        } else {
          return null;
        }

      default:
        return unifier.unify(x, y);
    }
  }
 /** a = S & a <: T imply S <: T or a = S & T <: a imply T <: S or S <: a & a <: T imply S <: T */
 private void upDown(
     List<PsiType> eqBounds, List<PsiType> upperBounds, PsiSubstitutor substitutor) {
   for (PsiType upperBound : upperBounds) {
     if (upperBound == null) continue;
     for (PsiType eqBound : eqBounds) {
       if (eqBound == null) continue;
       addConstraint(
           new StrictSubtypingConstraint(
               substitutor.substitute(upperBound), substitutor.substitute(eqBound)));
     }
   }
 }
  public static void replaceMovedMemberTypeParameters(
      final PsiElement member,
      final Iterable<PsiTypeParameter> parametersIterable,
      final PsiSubstitutor substitutor,
      final GroovyPsiElementFactory factory) {
    final Map<PsiElement, PsiElement> replacement = new LinkedHashMap<PsiElement, PsiElement>();
    for (PsiTypeParameter parameter : parametersIterable) {
      PsiType substitutedType = substitutor.substitute(parameter);
      if (substitutedType == null) {
        substitutedType = TypeConversionUtil.erasure(factory.createType(parameter));
      }

      PsiElement scopeElement = member instanceof GrField ? member.getParent() : member;
      for (PsiReference reference :
          ReferencesSearch.search(parameter, new LocalSearchScope(scopeElement))) {
        final PsiElement element = reference.getElement();
        final PsiElement parent = element.getParent();
        if (parent instanceof PsiTypeElement) {
          replacement.put(parent, factory.createTypeElement(substitutedType));
        } else if (element instanceof GrCodeReferenceElement
            && substitutedType instanceof PsiClassType) {
          replacement.put(
              element, factory.createReferenceElementByType((PsiClassType) substitutedType));
        }
      }
    }

    for (PsiElement element : replacement.keySet()) {
      if (element.isValid()) {
        element.replace(replacement.get(element));
      }
    }
  }
  @Nullable
  private static String formatTypeParameters(
      @NotNull final PsiSubstitutor substitutor, final PsiTypeParameter[] params) {
    final boolean space = showSpaceAfterComma(params[0]);
    StringBuilder buffer = new StringBuilder();
    buffer.append("<");
    for (int i = 0; i < params.length; i++) {
      final PsiTypeParameter param = params[i];
      final PsiType type = substitutor.substitute(param);
      if (type == null) {
        return "";
      }
      if (type instanceof PsiClassType && ((PsiClassType) type).getParameters().length > 0) {
        buffer.append(((PsiClassType) type).rawType().getPresentableText()).append("<...>");
      } else {
        buffer.append(type.getPresentableText());
      }

      if (i < params.length - 1) {
        buffer.append(",");
        if (space) {
          buffer.append(" ");
        }
      }
    }
    buffer.append(">");
    return buffer.toString();
  }
    @Override
    public boolean execute(PsiElement element, ResolveState state) {
      if (element instanceof PsiMethod || element instanceof PsiField) {
        String propertyName;
        PsiType type;

        if (element instanceof PsiMethod) {
          PsiMethod method = (PsiMethod) element;
          if (!GroovyPropertyUtils.isSimplePropertySetter(method)) return true;

          propertyName = GroovyPropertyUtils.getPropertyNameBySetter(method);
          if (propertyName == null) return true;

          type = method.getParameterList().getParameters()[0].getType();
        } else {
          type = ((PsiField) element).getType();
          propertyName = ((PsiField) element).getName();
        }

        if (((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC)) return true;

        if (myResult.containsKey(propertyName) || propertyName.equals(METACLASS)) return true;

        PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
        if (substitutor != null) {
          type = substitutor.substitute(type);
        }

        myResult.put(propertyName, new TypeCondition(type, element));
      }

      return true;
    }
 @Nullable
 private static PsiType getTypeFromMapAccess(@NotNull GrReferenceExpressionImpl ref) {
   // map access
   GrExpression qualifier = ref.getQualifierExpression();
   if (qualifier != null) {
     PsiType qType = qualifier.getNominalType();
     if (qType instanceof PsiClassType) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(ref.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, ref.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             return TypeConversionUtil.erasure(
                 substitutor.substitute(mapClass.getTypeParameters()[1]));
           }
         }
       }
     }
   }
   return null;
 }
 @Nullable
 private static PsiType getExpectedTypeArg(
     PsiElement context,
     int index,
     PsiClassType.ClassResolveResult expectedType,
     PsiSubstitutor currentSubstitutor,
     PsiTypeParameter[] params) {
   PsiClass expectedClass = expectedType.getElement();
   assert expectedClass != null;
   for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(expectedClass)) {
     final PsiType argSubstitution = expectedType.getSubstitutor().substitute(parameter);
     final PsiType paramSubstitution = currentSubstitutor.substitute(parameter);
     final PsiType substitution =
         JavaPsiFacade.getInstance(context.getProject())
             .getResolveHelper()
             .getSubstitutionForTypeParameter(
                 params[index],
                 paramSubstitution,
                 argSubstitution,
                 false,
                 PsiUtil.getLanguageLevel(context));
     if (substitution != null && substitution != PsiType.NULL) {
       return substitution;
     }
   }
   return null;
 }
  public String calcGenerics(@NotNull PsiElement context, InsertionContext insertionContext) {
    if (insertionContext.getCompletionChar() == '<') {
      return "";
    }

    assert context.isValid();
    if (myDiamond) {
      return "<>";
    }

    if (getObject() instanceof PsiClass) {
      PsiClass psiClass = (PsiClass) getObject();
      PsiResolveHelper resolveHelper =
          JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper();
      PsiSubstitutor substitutor = getSubstitutor();
      StringBuilder builder = new StringBuilder();
      for (PsiTypeParameter parameter : psiClass.getTypeParameters()) {
        PsiType substitute = substitutor.substitute(parameter);
        if (substitute == null
            || (PsiUtil.resolveClassInType(substitute) == parameter
                && resolveHelper.resolveReferencedClass(parameter.getName(), context)
                    != CompletionUtil.getOriginalOrSelf(parameter))) {
          return "";
        }
        if (builder.length() > 0) {
          builder.append(", ");
        }
        builder.append(substitute.getCanonicalText());
      }
      if (builder.length() > 0) {
        return "<" + builder + ">";
      }
    }
    return "";
  }
 private JavaResolveResult advancedResolveImpl() {
   final PsiElement resolve = resolveElement();
   if (resolve instanceof PsiClass) {
     final Map<PsiTypeParameter, PsiType> substitutionMap =
         new HashMap<PsiTypeParameter, PsiType>();
     int index = 0;
     for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable((PsiClass) resolve)) {
       if (index >= myTypeParameters.length) {
         final PsiTypeParameterListOwner parameterOwner = parameter.getOwner();
         if (parameterOwner == resolve) {
           substitutionMap.put(parameter, null);
         } else if (parameterOwner instanceof PsiClass) {
           PsiElement containingClass = myParent;
           while ((containingClass =
                   PsiTreeUtil.getParentOfType(containingClass, PsiClass.class, true))
               != null) {
             final PsiSubstitutor superClassSubstitutor =
                 TypeConversionUtil.getClassSubstitutor(
                     (PsiClass) parameterOwner, (PsiClass) containingClass, PsiSubstitutor.EMPTY);
             if (superClassSubstitutor != null) {
               substitutionMap.put(parameter, superClassSubstitutor.substitute(parameter));
               break;
             }
           }
         }
       } else {
         substitutionMap.put(parameter, myTypeParameters[index].getType());
       }
       index++;
     }
     return new CandidateInfo(resolve, PsiSubstitutorImpl.createSubstitutor(substitutionMap));
   } else {
     return new CandidateInfo(resolve, PsiSubstitutor.EMPTY);
   }
 }
 @Nullable
 private static PsiType getInferredTypes(
     GrReferenceExpressionImpl refExpr, @Nullable PsiElement resolved) {
   final GrExpression qualifier = refExpr.getQualifier();
   if (qualifier == null && !(resolved instanceof PsiClass)) {
     return TypeInferenceHelper.getCurrentContext().getVariableType(refExpr);
   } else if (qualifier != null) {
     // map access
     PsiType qType = qualifier.getType();
     if (qType instanceof PsiClassType && !(qType instanceof GrMapType)) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(refExpr.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, refExpr.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             return TypeConversionUtil.erasure(
                 substitutor.substitute(mapClass.getTypeParameters()[1]));
           }
         }
       }
     }
   }
   return null;
 }
  @NotNull
  private static PsiSubstitutor replaceVariables(Collection<InferenceVariable> inferenceVariables) {
    final List<InferenceVariable> targetVars = new ArrayList<InferenceVariable>();
    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    final InferenceVariable[] oldVars =
        inferenceVariables.toArray(new InferenceVariable[inferenceVariables.size()]);
    for (InferenceVariable variable : oldVars) {
      final InferenceVariable newVariable =
          new InferenceVariable(
              variable.getCallContext(), variable.getParameter(), variable.getName());
      substitutor =
          substitutor.put(
              variable,
              JavaPsiFacade.getElementFactory(variable.getProject()).createType(newVariable));
      targetVars.add(newVariable);
      if (variable.isThrownBound()) {
        newVariable.setThrownBound();
      }
    }

    for (int i = 0; i < targetVars.size(); i++) {
      InferenceVariable var = targetVars.get(i);
      for (InferenceBound boundType : InferenceBound.values()) {
        for (PsiType bound : oldVars[i].getBounds(boundType)) {
          var.addBound(substitutor.substitute(bound), boundType, null);
        }
      }
    }
    return substitutor;
  }
Example #14
0
 public GrImmediateClosureParameterImpl(
     @NotNull PsiParameter parameter, @NotNull PsiSubstitutor substitutor) {
   this(
       substitutor.substitute(getParameterType(parameter)),
       getParameterName(parameter),
       isParameterOptional(parameter),
       getDefaultInitializer(parameter));
 }
 public void testInferWithBounds1() throws Exception {
   PsiReferenceExpression ref = configure();
   JavaResolveResult resolveResult = ref.advancedResolve(false);
   PsiSubstitutor substitutor = resolveResult.getSubstitutor();
   PsiMethod method = (PsiMethod) resolveResult.getElement();
   PsiType type = substitutor.substitute(method.getTypeParameters()[0]);
   assertEquals("java.lang.String", type.getCanonicalText());
 }
  @Nullable
  public static PsiType getSubstitutedType(@Nullable PsiParameter parameter) {
    if (parameter == null) return null;

    final PsiType type = getType(parameter);

    if (type instanceof PsiArrayType) {
      return type;
    }

    final PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type);
    final PsiClass psiClass = result.getElement();
    if (psiClass == null) return type;

    final Set<PsiTypeParameter> usedTypeParameters = new HashSet<PsiTypeParameter>();
    RefactoringUtil.collectTypeParameters(usedTypeParameters, parameter);
    for (Iterator<PsiTypeParameter> iterator = usedTypeParameters.iterator();
        iterator.hasNext(); ) {
      PsiTypeParameter usedTypeParameter = iterator.next();
      if (parameter.getDeclarationScope() != usedTypeParameter.getOwner()) {
        iterator.remove();
      }
    }

    PsiSubstitutor subst = PsiSubstitutor.EMPTY;
    for (PsiTypeParameter usedTypeParameter : usedTypeParameters) {
      subst =
          subst.put(usedTypeParameter, TypeConversionUtil.typeParameterErasure(usedTypeParameter));
    }

    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    final Map<PsiTypeParameter, PsiType> typeMap = result.getSubstitutor().getSubstitutionMap();
    for (PsiTypeParameter typeParameter : typeMap.keySet()) {
      final PsiType psiType = typeMap.get(typeParameter);
      substitutor =
          substitutor.put(typeParameter, psiType != null ? subst.substitute(psiType) : null);
    }

    if (psiClass instanceof PsiTypeParameter) {
      return subst.substitute((PsiTypeParameter) psiClass);
    } else {
      return JavaPsiFacade.getElementFactory(parameter.getProject())
          .createType(psiClass, substitutor);
    }
  }
 @NotNull
 private static PsiType[] typesAtSite(
     @NotNull PsiType[] types1, @NotNull PsiSubstitutor siteSubstitutor1) {
   final PsiType[] types = PsiType.createArray(types1.length);
   for (int i = 0; i < types1.length; i++) {
     types[i] = siteSubstitutor1.substitute(types1[i]);
   }
   return types;
 }
  private int substituteToTypeParameters(
      PsiTypeElement typeElement,
      PsiTypeElement inplaceTypeElement,
      PsiType[] paramVals,
      PsiTypeParameter[] params,
      TemplateBuilder builder,
      PsiSubstitutor rawingSubstitutor,
      boolean toplevel) {
    PsiType type = inplaceTypeElement.getType();
    List<PsiType> types = new ArrayList<>();
    for (int i = 0; i < paramVals.length; i++) {
      PsiType val = paramVals[i];
      if (val == null) return SUBSTITUTED_NONE;
      if (type.equals(val)) {
        types.add(myFactory.createType(params[i]));
      }
    }

    if (!types.isEmpty()) {
      Project project = typeElement.getProject();
      PsiType substituted = rawingSubstitutor.substitute(type);
      if (!CommonClassNames.JAVA_LANG_OBJECT.equals(substituted.getCanonicalText())
          && (toplevel || substituted.equals(type))) {
        types.add(substituted);
      }

      builder.replaceElement(
          typeElement,
          new TypeExpression(project, types.toArray(PsiType.createArray(types.size()))));
      return toplevel ? SUBSTITUTED_IN_REF : SUBSTITUTED_IN_PARAMETERS;
    }

    boolean substituted = false;
    PsiJavaCodeReferenceElement ref = typeElement.getInnermostComponentReferenceElement();
    PsiJavaCodeReferenceElement inplaceRef =
        inplaceTypeElement.getInnermostComponentReferenceElement();
    if (ref != null) {
      LOG.assertTrue(inplaceRef != null);
      PsiTypeElement[] innerTypeElements = ref.getParameterList().getTypeParameterElements();
      PsiTypeElement[] inplaceInnerTypeElements =
          inplaceRef.getParameterList().getTypeParameterElements();
      for (int i = 0; i < innerTypeElements.length; i++) {
        substituted |=
            substituteToTypeParameters(
                    innerTypeElements[i],
                    inplaceInnerTypeElements[i],
                    paramVals,
                    params,
                    builder,
                    rawingSubstitutor,
                    false)
                != SUBSTITUTED_NONE;
      }
    }

    return substituted ? SUBSTITUTED_IN_PARAMETERS : SUBSTITUTED_NONE;
  }
 private static PsiParameter createNewParameter(
     JavaChangeInfo changeInfo, JavaParameterInfo newParm, PsiSubstitutor substitutor)
     throws IncorrectOperationException {
   final PsiParameterList list = changeInfo.getMethod().getParameterList();
   final PsiElementFactory factory =
       JavaPsiFacade.getInstance(list.getProject()).getElementFactory();
   final PsiType type = substitutor.substitute(newParm.createType(list, list.getManager()));
   return factory.createParameter(newParm.getName(), type);
 }
Example #20
0
  private static boolean changeClassTypeArgument(
      PsiMethod myMethod,
      Project project,
      PsiType superReturnType,
      PsiClass superClass,
      Editor editor,
      PsiType returnType) {
    if (superClass == null || !superClass.hasTypeParameters()) return true;
    final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType);
    if (superReturnTypeClass == null
        || !(superReturnTypeClass instanceof PsiTypeParameter
            || superReturnTypeClass.hasTypeParameters())) return true;

    final PsiClass derivedClass = myMethod.getContainingClass();
    if (derivedClass == null) return true;

    final PsiReferenceParameterList referenceParameterList =
        findTypeArgumentsList(superClass, derivedClass);
    if (referenceParameterList == null) return true;

    final PsiElement resolve =
        ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    if (!(resolve instanceof PsiClass)) return true;
    final PsiClass baseClass = (PsiClass) resolve;

    if (returnType instanceof PsiPrimitiveType) {
      returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass);
    }

    final PsiSubstitutor superClassSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY);
    final PsiType superReturnTypeInBaseClassType =
        superClassSubstitutor.substitute(superReturnType);
    final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
    final PsiSubstitutor psiSubstitutor =
        resolveHelper.inferTypeArguments(
            PsiTypesUtil.filterUnusedTypeParameters(
                superReturnTypeInBaseClassType, baseClass.getTypeParameters()),
            new PsiType[] {superReturnTypeInBaseClassType},
            new PsiType[] {returnType},
            PsiUtil.getLanguageLevel(superClass));

    final TypeMigrationRules rules = new TypeMigrationRules();
    final PsiSubstitutor compoundSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY)
            .putAll(psiSubstitutor);
    rules.setBoundScope(new LocalSearchScope(derivedClass));
    TypeMigrationProcessor.runHighlightingTypeMigration(
        project,
        editor,
        rules,
        referenceParameterList,
        JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));

    return false;
  }
  @Nullable
  @Override
  protected List<ClosureParameterInfo> getParameterInfos(
      InsertionContext context,
      PsiMethod method,
      PsiSubstitutor substitutor,
      Document document,
      int offset,
      PsiElement parent) {
    final String name = method.getName();
    if (!"eachWithIndex".equals(name)) return null;

    if (method instanceof GrGdkMethod) method = ((GrGdkMethod) method).getStaticMethod();

    final PsiClass containingClass = method.getContainingClass();
    if (containingClass == null) return null;

    final String qname = containingClass.getQualifiedName();

    if (!GroovyCommonClassNames.DEFAULT_GROOVY_METHODS.equals(qname)) return null;

    final PsiParameter[] parameters = method.getParameterList().getParameters();
    if (parameters.length != 2) return null;

    final PsiType type = parameters[0].getType();
    final PsiType collection = substitutor.substitute(type);

    final PsiType iterable = getIteratedType(parent, collection);
    if (iterable != null) {
      return Arrays.asList(
          new ClosureParameterInfo(iterable.getCanonicalText(), "entry"),
          new ClosureParameterInfo("int", "i"));
    }

    if (InheritanceUtil.isInheritor(collection, CommonClassNames.JAVA_UTIL_MAP)) {
      final PsiType[] typeParams = ((PsiClassType) collection).getParameters();

      final Project project = context.getProject();

      final PsiClass entry =
          JavaPsiFacade.getInstance(project)
              .findClass("java.util.Map.Entry", parent.getResolveScope());
      if (entry == null) return null;

      final PsiClassType entryType =
          JavaPsiFacade.getElementFactory(project).createType(entry, typeParams);

      return Arrays.asList(
          new ClosureParameterInfo(entryType.getCanonicalText(), "entry"),
          new ClosureParameterInfo("int", "i"));
    }

    return Arrays.asList(
        new ClosureParameterInfo(collection.getCanonicalText(), "entry"),
        new ClosureParameterInfo("int", "i"));
  }
  private static CompoundInitialState createState(InferenceSession topLevelSession) {
    final PsiSubstitutor topInferenceSubstitutor =
        replaceVariables(topLevelSession.getInferenceVariables());
    final Map<PsiElement, InitialInferenceState> nestedStates =
        new LinkedHashMap<PsiElement, InitialInferenceState>();

    final InferenceSessionContainer copy =
        new InferenceSessionContainer() {
          @Override
          public PsiSubstitutor findNestedSubstitutor(
              PsiElement arg, @Nullable PsiSubstitutor defaultSession) {
            // for the case foo(bar(a -> m())): top level inference won't touch lambda "a -> m()"
            // for the case foo(a -> bar(b -> m())): top level inference would go till nested lambda
            // "b -> m()" and the state from top level could be found here by "bar(b -> m())"
            // but proceeding with additional constraints from saved point would produce new
            // expression constraints with different inference variables (could be found in
            // myNestedSessions)
            // which won't be found in the system if we won't reject stored sessions in such cases
            final PsiSubstitutor substitutor = super.findNestedSubstitutor(arg, null);
            if (substitutor != null) {
              return substitutor;
            }

            final InitialInferenceState state =
                nestedStates.get(PsiTreeUtil.getParentOfType(arg, PsiCall.class));
            if (state != null) {
              return state.getInferenceSubstitutor();
            }
            return super.findNestedSubstitutor(arg, defaultSession);
          }
        };
    final Map<PsiElement, InferenceSession> nestedSessions =
        topLevelSession.getInferenceSessionContainer().myNestedSessions;
    for (Map.Entry<PsiElement, InferenceSession> entry : nestedSessions.entrySet()) {
      nestedStates.put(
          entry.getKey(),
          entry
              .getValue()
              .createInitialState(
                  copy, topLevelSession.getInferenceVariables(), topInferenceSubstitutor));
    }

    PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
    for (InferenceVariable variable : topLevelSession.getInferenceVariables()) {
      final PsiType instantiation = variable.getInstantiation();
      if (instantiation != PsiType.NULL) {
        final PsiClass psiClass =
            PsiUtil.resolveClassInClassTypeOnly(topInferenceSubstitutor.substitute(variable));
        if (psiClass instanceof InferenceVariable) {
          substitutor = substitutor.put((PsiTypeParameter) psiClass, instantiation);
        }
      }
    }

    return new CompoundInitialState(substitutor, nestedStates);
  }
  private static boolean checkSignaturesEqualInner(
      @NotNull MethodSignature subSignature,
      @NotNull MethodSignature superSignature,
      final PsiSubstitutor unifyingSubstitutor) {
    if (unifyingSubstitutor == null) return false;
    if (!areErasedParametersEqual(subSignature, superSignature)) return false;

    final PsiType[] subParameterTypes = subSignature.getParameterTypes();
    final PsiType[] superParameterTypes = superSignature.getParameterTypes();
    for (int i = 0; i < subParameterTypes.length; i++) {
      final PsiType type1 = unifyingSubstitutor.substitute(subParameterTypes[i]);
      final PsiType type2 = unifyingSubstitutor.substitute(superParameterTypes[i]);
      if (!Comparing.equal(type1, type2)) {
        return false;
      }
    }

    return true;
  }
 @NotNull
 private static PsiSubstitutor calculateMethodSubstitutor(
     @NotNull PsiTypeParameter[] typeParameters,
     @NotNull PsiMethod method,
     @NotNull PsiSubstitutor siteSubstitutor,
     @NotNull PsiType[] types1,
     @NotNull PsiType[] types2,
     @NotNull LanguageLevel languageLevel) {
   PsiSubstitutor substitutor =
       PsiResolveHelper.SERVICE
           .getInstance(method.getProject())
           .inferTypeArguments(typeParameters, types1, types2, languageLevel);
   for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(method)) {
     ProgressManager.checkCanceled();
     LOG.assertTrue(typeParameter != null);
     if (!substitutor.getSubstitutionMap().containsKey(typeParameter)) {
       PsiType type = siteSubstitutor.substitute(typeParameter);
       if (type instanceof PsiClassType && typeParameter.getOwner() == method) {
         final PsiClass aClass = ((PsiClassType) type).resolve();
         if (aClass instanceof PsiTypeParameter
             && ((PsiTypeParameter) aClass).getOwner() == method) {
           type = TypeConversionUtil.erasure(type, siteSubstitutor);
         }
       }
       substitutor = substitutor.put(typeParameter, type);
     } else {
       final PsiType type = substitutor.substitute(typeParameter);
       if (type instanceof PsiClassType) {
         final PsiClass aClass = ((PsiClassType) type).resolve();
         if (aClass instanceof PsiTypeParameter) {
           substitutor =
               substitutor.put(
                   typeParameter,
                   JavaPsiFacade.getElementFactory(aClass.getProject())
                       .createType(aClass, siteSubstitutor));
         }
       }
     }
   }
   return substitutor;
 }
  public static PsiType[] getErasedParameterTypes(MethodSignature signature) {
    PsiType[] parameterTypes = signature.getParameterTypes();
    if (parameterTypes.length == 0) return PsiType.EMPTY_ARRAY;

    PsiSubstitutor substitutor = signature.getSubstitutor();
    PsiType[] erasedTypes = new PsiType[parameterTypes.length];
    for (int i = 0; i < parameterTypes.length; i++) {
      erasedTypes[i] =
          TypeConversionUtil.erasure(substitutor.substitute(parameterTypes[i]), substitutor);
    }
    return erasedTypes;
  }
  public static PsiType captureReturnType(
      PsiMethodCallExpression call,
      PsiMethod method,
      PsiType ret,
      JavaResolveResult result,
      LanguageLevel languageLevel) {
    PsiSubstitutor substitutor = result.getSubstitutor();
    PsiType substitutedReturnType = substitutor.substitute(ret);
    if (substitutedReturnType == null) {
      return TypeConversionUtil.erasure(ret);
    }

    if (InferenceSession.wasUncheckedConversionPerformed(call)) {
      // 18.5.2
      // if unchecked conversion was necessary, then this substitution provides the parameter types
      // of the invocation type,
      // while the return type and thrown types are given by the erasure of m's type (without
      // applying θ').
      // due to https://bugs.openjdk.java.net/browse/JDK-8135087 erasure is called on
      // substitutedReturnType and not on ret type itself as by spec
      return TypeConversionUtil.erasure(substitutedReturnType);
    }

    // 15.12.2.6. Method Invocation Type
    // If unchecked conversion was necessary for the method to be applicable,
    // the parameter types of the invocation type are the parameter types of the method's type,
    // and the return type and thrown types are given by the erasures of the return type and thrown
    // types of the method's type.
    if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8)
        && (method.hasTypeParameters()
            || JavaVersionService.getInstance().isAtLeast(call, JavaSdkVersion.JDK_1_8))
        && result instanceof MethodCandidateInfo
        && ((MethodCandidateInfo) result).isApplicable()) {
      final PsiType[] args = call.getArgumentList().getExpressionTypes();
      final boolean allowUncheckedConversion = false;
      final int applicabilityLevel =
          PsiUtil.getApplicabilityLevel(
              method, substitutor, args, languageLevel, allowUncheckedConversion, true);
      if (applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE) {
        return TypeConversionUtil.erasure(substitutedReturnType);
      }
    }

    if (PsiUtil.isRawSubstitutor(method, substitutor)) {
      final PsiType returnTypeErasure = TypeConversionUtil.erasure(ret);
      if (Comparing.equal(TypeConversionUtil.erasure(substitutedReturnType), returnTypeErasure)) {
        return returnTypeErasure;
      }
    }
    return PsiUtil.captureToplevelWildcards(substitutedReturnType, call);
  }
    public PsiType substitute(final PsiType t) {
      if (t instanceof PsiWildcardType) {
        final PsiWildcardType wcType = (PsiWildcardType) t;
        final PsiType bound = wcType.getBound();

        if (bound == null) {
          return t;
        }

        final PsiManager manager = PsiManager.getInstance(myProject);
        final PsiType subst = substitute(bound);
        if (subst == null) return null;
        return subst instanceof PsiWildcardType
            ? subst
            : wcType.isExtends()
                ? PsiWildcardType.createExtends(manager, subst)
                : PsiWildcardType.createSuper(manager, subst);
      } else if (t instanceof PsiTypeVariable) {
        final PsiType b = apply(t);

        if (b instanceof Bottom || b instanceof PsiTypeVariable) {
          return null;
        }

        return substitute(b);
      } else if (t instanceof Bottom) {
        return null;
      } else if (t instanceof PsiArrayType) {
        return substitute(((PsiArrayType) t).getComponentType()).createArrayType();
      } else if (t instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult result = ((PsiClassType) t).resolveGenerics();

        final PsiClass aClass = result.getElement();
        final PsiSubstitutor aSubst = result.getSubstitutor();

        if (aClass != null) {
          PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;

          for (final PsiTypeParameter parm : aSubst.getSubstitutionMap().keySet()) {
            final PsiType type = aSubst.substitute(parm);

            theSubst = theSubst.put(parm, substitute(type));
          }

          return JavaPsiFacade.getInstance(aClass.getProject())
              .getElementFactory()
              .createType(aClass, theSubst);
        }
      }
      return t;
    }
  /**
   * @param methodSignature method signature
   * @param superMethodSignature super method signature
   * @return null if signatures do not match
   */
  @Nullable
  public static PsiSubstitutor getSuperMethodSignatureSubstitutor(
      @NotNull MethodSignature methodSignature, @NotNull MethodSignature superMethodSignature) {
    PsiSubstitutor result =
        getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature);
    if (result == null) return null;

    PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters();
    PsiTypeParameter[] superTypeParameters = superMethodSignature.getTypeParameters();
    PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor();

    // check bounds
    for (int i = 0; i < methodTypeParameters.length; i++) {
      PsiTypeParameter methodTypeParameter = methodTypeParameters[i];
      PsiTypeParameter superTypeParameter = superTypeParameters[i];
      final Set<PsiType> methodSupers = new HashSet<PsiType>();
      for (PsiClassType methodSuper : methodTypeParameter.getSuperTypes()) {
        methodSupers.add(methodSubstitutor.substitute(methodSuper));
      }

      final Set<PsiType> superSupers = new HashSet<PsiType>();
      for (PsiClassType superSuper : superTypeParameter.getSuperTypes()) {
        superSupers.add(
            methodSubstitutor.substitute(
                PsiUtil.captureToplevelWildcards(
                    result.substitute(superSuper), methodTypeParameter)));
      }
      methodSupers.remove(
          PsiType.getJavaLangObject(
              methodTypeParameter.getManager(), methodTypeParameter.getResolveScope()));
      superSupers.remove(
          PsiType.getJavaLangObject(
              superTypeParameter.getManager(), superTypeParameter.getResolveScope()));
      if (!methodSupers.equals(superSupers)) return null;
    }

    return result;
  }
Example #29
0
 public static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) {
   final Map<PsiTypeParameter, PsiType> map = s1.getSubstitutionMap();
   Map<PsiTypeParameter, PsiType> result = new THashMap<PsiTypeParameter, PsiType>(map.size());
   for (PsiTypeParameter parameter : map.keySet()) {
     result.put(parameter, s2.substitute(map.get(parameter)));
   }
   final Map<PsiTypeParameter, PsiType> map2 = s2.getSubstitutionMap();
   for (PsiTypeParameter parameter : map2.keySet()) {
     if (!result.containsKey(parameter)) {
       result.put(parameter, map2.get(parameter));
     }
   }
   return PsiSubstitutorImpl.createSubstitutor(result);
 }
 static boolean isArgumentInVarargPosition(
     PsiExpression[] expressions, int ei, PsiParameter varargParam, PsiSubstitutor substitutor) {
   if (varargParam == null) return false;
   final PsiExpression expression = expressions[ei];
   if (expression == null
       || TypeConversionUtil.areTypesAssignmentCompatible(
           substitutor.substitute(((PsiEllipsisType) varargParam.getType()).getComponentType()),
           expression)) {
     final int lastExprIdx = expressions.length - 1;
     if (ei == lastExprIdx) return true;
     return expressions[lastExprIdx].getType() != PsiType.NULL;
   }
   return false;
 }