private List<TypeProjection> substituteTypeArguments(
      List<TypeParameterDescriptor> typeParameters,
      List<TypeProjection> typeArguments,
      int recursionDepth)
      throws SubstitutionException {
    List<TypeProjection> substitutedArguments =
        new ArrayList<TypeProjection>(typeParameters.size());
    for (int i = 0; i < typeParameters.size(); i++) {
      TypeParameterDescriptor typeParameter = typeParameters.get(i);
      TypeProjection typeArgument = typeArguments.get(i);

      TypeProjection substitutedTypeArgument = unsafeSubstitute(typeArgument, recursionDepth + 1);

      switch (conflictType(
          typeParameter.getVariance(), substitutedTypeArgument.getProjectionKind())) {
        case NO_CONFLICT:
          // if the corresponding type parameter is already co/contra-variant, there's not need for
          // an explicit projection
          if (typeParameter.getVariance() != Variance.INVARIANT
              && !substitutedTypeArgument.isStarProjection()) {
            substitutedTypeArgument =
                new TypeProjectionImpl(Variance.INVARIANT, substitutedTypeArgument.getType());
          }
          break;
        case OUT_IN_IN_POSITION:
        case IN_IN_OUT_POSITION:
          substitutedTypeArgument = TypeUtils.makeStarProjection(typeParameter);
          break;
      }

      substitutedArguments.add(substitutedTypeArgument);
    }
    return substitutedArguments;
  }
  @NotNull
  private VarargCheckResult checkVarargInSuperFunctions(
      @NotNull ValueParameterDescriptor originalParam) {
    boolean someSupersVararg = false;
    boolean someSupersNotVararg = false;
    for (FunctionDescriptor superFunction : superFunctions) {
      if (superFunction.getValueParameters().get(originalParam.getIndex()).getVarargElementType()
          != null) {
        someSupersVararg = true;
      } else {
        someSupersNotVararg = true;
      }
    }

    JetType originalVarargElementType = originalParam.getVarargElementType();
    JetType originalType = originalParam.getType();

    if (someSupersVararg && someSupersNotVararg) {
      reportError("Incompatible super methods: some have vararg parameter, some have not");
      return new VarargCheckResult(originalType, originalVarargElementType != null);
    }

    KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
    if (someSupersVararg && originalVarargElementType == null) {
      // convert to vararg

      assert isArrayType(originalType);

      if (builtIns.isPrimitiveArray(originalType)) {
        // replace IntArray? with IntArray
        return new VarargCheckResult(TypeUtils.makeNotNullable(originalType), true);
      }

      // replace Array<out Foo>? with Array<Foo>
      JetType varargElementType = builtIns.getArrayElementType(originalType);
      return new VarargCheckResult(builtIns.getArrayType(INVARIANT, varargElementType), true);
    } else if (someSupersNotVararg && originalVarargElementType != null) {
      // convert to non-vararg

      assert isArrayType(originalType);

      if (builtIns.isPrimitiveArray(originalType)) {
        // replace IntArray with IntArray?
        return new VarargCheckResult(TypeUtils.makeNullable(originalType), false);
      }

      // replace Array<Foo> with Array<out Foo>?
      return new VarargCheckResult(
          TypeUtils.makeNullable(
              builtIns.getArrayType(Variance.OUT_VARIANCE, originalVarargElementType)),
          false);
    }

    return new VarargCheckResult(originalType, originalVarargElementType != null);
  }
  private Set<TypeElement> processDelegateMethods() {
    Set<Element> delegateMethods = (Set) getElements(QueryDelegate.class);
    Set<TypeElement> typeElements = new HashSet<TypeElement>();

    for (Element delegateMethod : delegateMethods) {
      ExecutableElement method = (ExecutableElement) delegateMethod;
      Element element = delegateMethod.getEnclosingElement();
      String name = method.getSimpleName().toString();
      Type delegateType = typeFactory.getType(element.asType(), true);
      Type returnType = typeFactory.getType(method.getReturnType(), true);
      List<Parameter> parameters = elementHandler.transformParams(method.getParameters());
      // remove first element
      parameters = parameters.subList(1, parameters.size());

      EntityType entityType = null;
      for (AnnotationMirror annotation : delegateMethod.getAnnotationMirrors()) {
        if (TypeUtils.isAnnotationMirrorOfType(annotation, QueryDelegate.class)) {
          TypeMirror type = TypeUtils.getAnnotationValueAsTypeMirror(annotation, "value");
          if (type != null) {
            entityType = typeFactory.getEntityType(type, true);
          }
        }
      }

      if (entityType != null) {
        registerTypeElement(entityType.getFullName(), (TypeElement) element);
        entityType.addDelegate(
            new Delegate(entityType, delegateType, name, parameters, returnType));
        TypeElement typeElement =
            processingEnv.getElementUtils().getTypeElement(entityType.getFullName());
        boolean isAnnotated = false;
        for (Class<? extends Annotation> ann : conf.getEntityAnnotations()) {
          if (typeElement.getAnnotation(ann) != null) {
            isAnnotated = true;
          }
        }
        if (isAnnotated) {
          // handle also properties of entity type
          typeElements.add(
              processingEnv.getElementUtils().getTypeElement(entityType.getFullName()));
        } else {
          // skip handling properties
          context.extensionTypes.put(entityType.getFullName(), entityType);
          context.allTypes.put(entityType.getFullName(), entityType);
        }
      }
    }

    return typeElements;
  }
  /**
   * Registers an object with the specified clazz and object.
   *
   * @param clazz the class which is used as the key.
   * @param object the object, or the value of the mapping
   * @param context the secondary key. It is used to register multiple objects to the same primary
   *     key (the clazz parameter in this case).
   */
  public void register(Class<?> clazz, T object, K context) {
    if (clazz == null) {
      throw new IllegalArgumentException("Parameter clazz cannot be null");
    }

    // register primitive type automatically
    if (TypeUtils.isPrimitiveWrapper(clazz)) {
      Class<?> primitiveType = TypeUtils.convertWrapperToPrimitiveType(clazz);
      register(primitiveType, object, context);
    }

    Cache<K, T> cache = initCache(clazz);
    cache.setObject(context, object);
  }
  private void handleEmbeddedType(Element element, Set<TypeElement> elements) {
    TypeMirror type = element.asType();
    if (element.getKind() == ElementKind.METHOD) {
      type = ((ExecutableElement) element).getReturnType();
    }
    String typeName = type.toString();

    if (typeName.startsWith(Collection.class.getName())
        || typeName.startsWith(List.class.getName())
        || typeName.startsWith(Set.class.getName())) {
      type = ((DeclaredType) type).getTypeArguments().get(0);

    } else if (typeName.startsWith(Map.class.getName())) {
      type = ((DeclaredType) type).getTypeArguments().get(1);
    }

    TypeElement typeElement = typeExtractor.visit(type);

    if (typeElement != null
        && !TypeUtils.hasAnnotationOfType(typeElement, conf.getEntityAnnotations())) {
      if (!typeElement.getQualifiedName().toString().startsWith("java.")) {
        elements.add(typeElement);
      }
    }
  }
  @NotNull
  private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>>
      getSuperclassToFunctionsMultimap(
          @NotNull PsiMethodWrapper method,
          @NotNull BindingContext bindingContext,
          @NotNull ClassDescriptor containingClass) {
    Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create();

    Name functionName = Name.identifier(method.getName());
    int parameterCount = method.getParameters().size();

    for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) {
      ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor();
      assert klass != null;
      FqName fqName = DescriptorUtils.getFQName(klass).toSafe();

      for (FunctionDescriptor fun :
          klass.getDefaultType().getMemberScope().getFunctions(functionName)) {
        if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) {
          PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
          if (declaration instanceof PsiMethod) {
            result.put(fqName, Pair.create(fun, (PsiMethod) declaration));
          } // else declaration is null or JetNamedFunction: both cases are processed later
        }
      }
    }
    return result;
  }
  // Returns list with type arguments info from supertypes
  // Example:
  //     - Foo<A, B> is a subtype of Bar<A, List<B>>, Baz<Boolean, A>
  //     - input: klass = Foo, typesFromSuper = [Bar<String, List<Int>>, Baz<Boolean, CharSequence>]
  //     - output[0] = [String, CharSequence], output[1] = []
  private static List<List<TypeProjectionAndVariance>> calculateTypeArgumentsFromSuper(
      @NotNull ClassDescriptor klass, @NotNull Collection<TypeAndVariance> typesFromSuper) {
    // For each superclass of klass and its parameters, hold their mapping to klass' parameters
    // #0 of Bar ->  A
    // #1 of Bar ->  List<B>
    // #0 of Baz ->  Boolean
    // #1 of Baz ->  A
    // #0 of Foo ->  A (mapped to itself)
    // #1 of Foo ->  B (mapped to itself)
    Multimap<TypeConstructor, TypeProjection> substitution =
        SubstitutionUtils.buildDeepSubstitutionMultimap(
            TypeUtils.makeUnsubstitutedType(klass, JetScope.EMPTY));

    // for each parameter of klass, hold arguments in corresponding supertypes
    List<List<TypeProjectionAndVariance>> parameterToArgumentsFromSuper = Lists.newArrayList();
    for (TypeParameterDescriptor ignored : klass.getTypeConstructor().getParameters()) {
      parameterToArgumentsFromSuper.add(new ArrayList<TypeProjectionAndVariance>());
    }

    // Enumerate all types from super and all its parameters
    for (TypeAndVariance typeFromSuper : typesFromSuper) {
      for (TypeParameterDescriptor parameter :
          typeFromSuper.type.getConstructor().getParameters()) {
        TypeProjection argument = typeFromSuper.type.getArguments().get(parameter.getIndex());

        // for given example, this block is executed four times:
        // 1. typeFromSuper = Bar<String, List<Int>>,      parameter = "#0 of Bar",  argument =
        // String
        // 2. typeFromSuper = Bar<String, List<Int>>,      parameter = "#1 of Bar",  argument =
        // List<Int>
        // 3. typeFromSuper = Baz<Boolean, CharSequence>,  parameter = "#0 of Baz",  argument =
        // Boolean
        // 4. typeFromSuper = Baz<Boolean, CharSequence>,  parameter = "#1 of Baz",  argument =
        // CharSequence

        // if it is mapped to klass' parameter, then store it into map
        for (TypeProjection projection : substitution.get(parameter.getTypeConstructor())) {
          // 1. projection = A
          // 2. projection = List<B>
          // 3. projection = Boolean
          // 4. projection = A
          ClassifierDescriptor classifier =
              projection.getType().getConstructor().getDeclarationDescriptor();

          // this condition is true for 1 and 4, false for 2 and 3
          if (classifier instanceof TypeParameterDescriptor
              && classifier.getContainingDeclaration() == klass) {
            int parameterIndex = ((TypeParameterDescriptor) classifier).getIndex();
            Variance effectiveVariance =
                parameter.getVariance().superpose(typeFromSuper.varianceOfPosition);
            parameterToArgumentsFromSuper
                .get(parameterIndex)
                .add(new TypeProjectionAndVariance(argument, effectiveVariance));
          }
        }
      }
    }
    return parameterToArgumentsFromSuper;
  }
 private void assertSupertypes(String typeStr, String... supertypeStrs) {
   Set<JetType> allSupertypes = TypeUtils.getAllSupertypes(makeType(scopeWithImports, typeStr));
   Set<JetType> expected = Sets.newHashSet();
   for (String supertypeStr : supertypeStrs) {
     JetType supertype = makeType(scopeWithImports, supertypeStr);
     expected.add(supertype);
   }
   assertEquals(expected, allSupertypes);
 }
 private void assertIntersection(String expected, String... types) {
   Set<JetType> typesToIntersect = new LinkedHashSet<JetType>();
   for (String type : types) {
     typesToIntersect.add(makeType(type));
   }
   JetType result = TypeUtils.intersect(JetTypeChecker.DEFAULT, typesToIntersect);
   //        assertNotNull("Intersection is null for " + typesToIntersect, result);
   assertEquals(makeType(expected), result);
 }
Exemple #10
0
  private void makePrimitive(@NotNull PrimitiveType primitiveType) {
    JetType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString());
    JetType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString());

    primitiveTypeToNullableJetType.put(primitiveType, TypeUtils.makeNullable(type));
    primitiveTypeToArrayJetType.put(primitiveType, arrayType);
    primitiveJetTypeToJetArrayType.put(type, arrayType);
    jetArrayTypeToPrimitiveJetType.put(arrayType, type);
  }
 private static Map<ClassDescriptor, JetType> getSuperclassToSupertypeMap(
     ClassDescriptor containingClass) {
   Map<ClassDescriptor, JetType> superclassToSupertype = Maps.newHashMap();
   for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) {
     ClassifierDescriptor superclass = supertype.getConstructor().getDeclarationDescriptor();
     assert superclass instanceof ClassDescriptor;
     superclassToSupertype.put((ClassDescriptor) superclass, supertype);
   }
   return superclassToSupertype;
 }
class InvocationHandlerGenerator implements CallbackGenerator {
  public static final InvocationHandlerGenerator INSTANCE = new InvocationHandlerGenerator();

  private static final Type INVOCATION_HANDLER =
      TypeUtils.parseType("net.sf.cglib.proxy.InvocationHandler");
  private static final Type UNDECLARED_THROWABLE_EXCEPTION =
      TypeUtils.parseType("net.sf.cglib.proxy.UndeclaredThrowableException");
  private static final Type METHOD = TypeUtils.parseType("java.lang.reflect.Method");
  private static final Signature INVOKE =
      TypeUtils.parseSignature("Object invoke(Object, java.lang.reflect.Method, Object[])");

  public void generate(ClassEmitter ce, Context context, List methods) {
    for (Iterator it = methods.iterator(); it.hasNext(); ) {
      MethodInfo method = (MethodInfo) it.next();
      Signature impl = context.getImplSignature(method);
      ce.declare_field(Constants.PRIVATE_FINAL_STATIC, impl.getName(), METHOD, null);

      CodeEmitter e = context.beginMethod(ce, method);
      Block handler = e.begin_block();
      context.emitCallback(e, context.getIndex(method));
      e.load_this();
      e.getfield(impl.getName());
      e.create_arg_array();
      e.invoke_interface(INVOCATION_HANDLER, INVOKE);
      e.unbox(method.getSignature().getReturnType());
      e.return_value();
      handler.end();
      EmitUtils.wrap_undeclared_throwable(
          e, handler, method.getExceptionTypes(), UNDECLARED_THROWABLE_EXCEPTION);
      e.end_method();
    }
  }

  public void generateStatic(CodeEmitter e, Context context, List methods) {
    for (Iterator it = methods.iterator(); it.hasNext(); ) {
      MethodInfo method = (MethodInfo) it.next();
      EmitUtils.load_method(e, method);
      e.putfield(context.getImplSignature(method).getName());
    }
  }
}
@SuppressWarnings({"rawtypes"})
class DispatcherGenerator implements CallbackGenerator {
  public static final DispatcherGenerator INSTANCE = new DispatcherGenerator(false);
  public static final DispatcherGenerator PROXY_REF_INSTANCE = new DispatcherGenerator(true);

  private static final Type DISPATCHER = TypeUtils.parseType("ext.jtester.cglib.proxy.Dispatcher");
  private static final Type PROXY_REF_DISPATCHER =
      TypeUtils.parseType("ext.jtester.cglib.proxy.ProxyRefDispatcher");
  private static final Signature LOAD_OBJECT = TypeUtils.parseSignature("Object loadObject()");
  private static final Signature PROXY_REF_LOAD_OBJECT =
      TypeUtils.parseSignature("Object loadObject(Object)");

  private boolean proxyRef;

  private DispatcherGenerator(boolean proxyRef) {
    this.proxyRef = proxyRef;
  }

  public void generate(ClassEmitter ce, Context context, List methods) {
    for (Iterator it = methods.iterator(); it.hasNext(); ) {
      MethodInfo method = (MethodInfo) it.next();
      if (!TypeUtils.isProtected(method.getModifiers())) {
        CodeEmitter e = context.beginMethod(ce, method);
        context.emitCallback(e, context.getIndex(method));
        if (proxyRef) {
          e.load_this();
          e.invoke_interface(PROXY_REF_DISPATCHER, PROXY_REF_LOAD_OBJECT);
        } else {
          e.invoke_interface(DISPATCHER, LOAD_OBJECT);
        }
        e.checkcast(method.getClassInfo().getType());
        e.load_args();
        e.invoke(method);
        e.return_value();
        e.end_method();
      }
    }
  }

  public void generateStatic(CodeEmitter e, Context context, List methods) {}
}
Exemple #14
0
  public static boolean shouldRecordInitializerForProperty(
      @NotNull VariableDescriptor variable, @NotNull KotlinType type) {
    if (variable.isVar() || type.isError()) return false;

    if (TypeUtils.acceptsNullable(type)) return true;

    KotlinBuiltIns builtIns = getBuiltIns(variable);
    return KotlinBuiltIns.isPrimitiveType(type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type);
  }
 @NotNull
 public KotlinType getArrayElementType(@NotNull KotlinType arrayType) {
   if (isArray(arrayType)) {
     if (arrayType.getArguments().size() != 1) {
       throw new IllegalStateException();
     }
     return arrayType.getArguments().get(0).getType();
   }
   KotlinType primitiveType =
       kotlinArrayTypeToPrimitiveKotlinType.get(TypeUtils.makeNotNullable(arrayType));
   if (primitiveType == null) {
     throw new IllegalStateException("not array: " + arrayType);
   }
   return primitiveType;
 }
 public void generate(ClassEmitter ce, Context context, List methods) {
   for (Iterator it = methods.iterator(); it.hasNext(); ) {
     MethodInfo method = (MethodInfo) it.next();
     if (!TypeUtils.isProtected(method.getModifiers())) {
       CodeEmitter e = context.beginMethod(ce, method);
       context.emitCallback(e, context.getIndex(method));
       if (proxyRef) {
         e.load_this();
         e.invoke_interface(PROXY_REF_DISPATCHER, PROXY_REF_LOAD_OBJECT);
       } else {
         e.invoke_interface(DISPATCHER, LOAD_OBJECT);
       }
       e.checkcast(method.getClassInfo().getType());
       e.load_args();
       e.invoke(method);
       e.return_value();
       e.end_method();
     }
   }
 }
 private Set<TypeElement> getAnnotationlessSupertypes(Set<TypeElement> elements) {
   Set<TypeElement> rv = new HashSet<TypeElement>();
   for (TypeElement element : elements) {
     TypeMirror superTypeMirror = element.getSuperclass();
     while (superTypeMirror != null) {
       TypeElement superTypeElement =
           (TypeElement) processingEnv.getTypeUtils().asElement(superTypeMirror);
       if (superTypeElement != null
           && !superTypeElement.toString().startsWith("java.lang.")
           && !TypeUtils.hasAnnotationOfType(superTypeElement, conf.getEntityAnnotations())) {
         rv.add(superTypeElement);
         superTypeMirror = superTypeElement.getSuperclass();
         if (superTypeMirror instanceof NoType) {
           superTypeMirror = null;
         }
       } else {
         superTypeMirror = null;
       }
     }
   }
   return rv;
 }
  /**
   * Gets registered object from CacheMap. The algorithm used to look up is <br>
   * 1. First check for exact match with clazz and context.<br>
   * 2. If didn't find, look for interfaces that clazz implements using the exact context.<br>
   * 3. If still didn't find, look for super class of clazz using the exact context. <br>
   * 4. If still didn't find, using the exact clazz with default context.<br>
   * 5. If still didn't find, return null.<br>
   * If found a match in step 1, 2, 3 or 4, it will return the registered object immediately.
   *
   * @param clazz the class which is used as the primary key.
   * @param context the context which is used as the secondary key. This parameter could be null in
   *     which case the default context is used.
   * @return registered object the object associated with the class and the context.
   */
  public T getRegisteredObject(Class<?> clazz, K context) {
    if (clazz == null) {
      return null;
    }

    Cache<K, T> cache = getCache(clazz);

    if (cache == null || !cache.containsKey(context)) {
      List<Class<?>> classesToSearch = new ArrayList<>();

      classesToSearch.add(clazz);
      if (TypeUtils.isPrimitive(clazz)) {
        classesToSearch.add(TypeUtils.convertPrimitiveToWrapperType(clazz));
      } else if (TypeUtils.isPrimitiveWrapper(clazz)) {
        classesToSearch.add(TypeUtils.convertWrapperToPrimitiveType(clazz));
      }

      // Direct super interfaces, recursively
      addAllInterfaces(classesToSearch, clazz);

      Class<?> superClass = clazz;
      // Direct super class, recursively
      while (!superClass.isInterface()) {
        superClass = superClass.getSuperclass();
        if (superClass != null) {
          classesToSearch.add(superClass);
          addAllInterfaces(classesToSearch, superClass);
        } else {
          break;
        }
      }

      if (!classesToSearch.contains(Object.class)) {
        classesToSearch.add(Object.class); // use Object as default fallback.
      }

      // search to match context first
      for (Class<?> c : classesToSearch) {
        Cache<K, T> cacheForClass = getCache(c);
        if (cacheForClass != null) {
          T object = cacheForClass.getObject(context);
          if (object != null) {
            return object;
          }
        }
      }

      // fall back to default context
      if (!_defaultContext.equals(context)) {
        for (Class<?> c : classesToSearch) {
          Cache<K, T> cacheForClass = getCache(c);
          if (cacheForClass != null) {
            T object = cacheForClass.getObject(_defaultContext);
            if (object != null) {
              return object;
            }
          }
        }
      }
    }

    if (cache != null) {
      T object = cache.getObject(context);
      if (object == null && !_defaultContext.equals(context)) {
        return getRegisteredObject(clazz, _defaultContext);
      }
      if (object != null) {
        return object;
      }
    }

    return null;
  }
  private void addConstraint(
      @NotNull ConstraintKind constraintKind,
      @NotNull JetType subjectType,
      @Nullable JetType constrainingType,
      @NotNull ConstraintPosition constraintPosition) {

    if (constrainingType == TypeUtils.NO_EXPECTED_TYPE
        || constrainingType == DONT_CARE
        || constrainingType == CANT_INFER) {
      return;
    }

    if (constrainingType == null
        || (ErrorUtils.isErrorType(constrainingType)
            && constrainingType != PLACEHOLDER_FUNCTION_TYPE)) {
      hasErrorInConstrainingTypes = true;
      return;
    }

    assert subjectType != TypeUtils.NO_EXPECTED_TYPE
        : "Subject type shouldn't be NO_EXPECTED_TYPE (in position " + constraintPosition + " )";
    if (ErrorUtils.isErrorType(subjectType)) return;

    DeclarationDescriptor subjectTypeDescriptor =
        subjectType.getConstructor().getDeclarationDescriptor();

    KotlinBuiltIns kotlinBuiltIns = KotlinBuiltIns.getInstance();
    if (constrainingType == PLACEHOLDER_FUNCTION_TYPE) {
      if (!kotlinBuiltIns.isFunctionOrExtensionFunctionType(subjectType)) {
        if (subjectTypeDescriptor instanceof TypeParameterDescriptor
            && typeParameterConstraints.get(subjectTypeDescriptor) != null) {
          // a constraint binds type parameter and any function type, so there is no new info and no
          // error
          return;
        }
        errorConstraintPositions.add(constraintPosition);
      }
      return;
    }

    // todo temporary hack
    // function literal without declaring receiver type { x -> ... }
    // can be considered as extension function if one is expected
    // (special type constructor for function/ extension function should be introduced like
    // PLACEHOLDER_FUNCTION_TYPE)
    if (constraintKind == SUB_TYPE
        && kotlinBuiltIns.isFunctionType(constrainingType)
        && kotlinBuiltIns.isExtensionFunctionType(subjectType)) {
      constrainingType = createCorrespondingExtensionFunctionType(constrainingType, DONT_CARE);
    }

    DeclarationDescriptor constrainingTypeDescriptor =
        constrainingType.getConstructor().getDeclarationDescriptor();

    if (subjectTypeDescriptor instanceof TypeParameterDescriptor) {
      TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) subjectTypeDescriptor;
      TypeConstraintsImpl typeConstraints = typeParameterConstraints.get(typeParameter);
      if (typeConstraints != null) {
        if (TypeUtils.dependsOnTypeParameterConstructors(
            constrainingType, Collections.singleton(DONT_CARE.getConstructor()))) {
          return;
        }
        if (subjectType.isNullable() && constrainingType.isNullable()) {
          constrainingType = TypeUtils.makeNotNullable(constrainingType);
        }
        typeConstraints.addBound(constraintKind, constrainingType);
        return;
      }
    }
    if (constrainingTypeDescriptor instanceof TypeParameterDescriptor) {
      assert typeParameterConstraints.get(constrainingTypeDescriptor) == null
          : "Constraining type contains type variable " + constrainingTypeDescriptor.getName();
    }
    if (constraintKind == SUB_TYPE && kotlinBuiltIns.isNothingOrNullableNothing(constrainingType)) {
      // following constraints are always true:
      // 'Nothing' is a subtype of any type
      if (!constrainingType.isNullable()) return;
      // 'Nothing?' is a subtype of nullable type
      if (subjectType.isNullable()) return;
    }
    if (!(constrainingTypeDescriptor instanceof ClassDescriptor)
        || !(subjectTypeDescriptor instanceof ClassDescriptor)) {
      errorConstraintPositions.add(constraintPosition);
      return;
    }
    switch (constraintKind) {
      case SUB_TYPE:
        {
          if (kotlinBuiltIns.isNothingOrNullableNothing(constrainingType)) break;
          JetType correspondingSupertype =
              TypeCheckingProcedure.findCorrespondingSupertype(constrainingType, subjectType);
          if (correspondingSupertype != null) {
            constrainingType = correspondingSupertype;
          }
          break;
        }
      case SUPER_TYPE:
        {
          if (kotlinBuiltIns.isNothingOrNullableNothing(subjectType)) break;
          JetType correspondingSupertype =
              TypeCheckingProcedure.findCorrespondingSupertype(subjectType, constrainingType);
          if (correspondingSupertype != null) {
            subjectType = correspondingSupertype;
          }
        }
      case EQUAL: // nothing
    }
    if (constrainingType.getConstructor() != subjectType.getConstructor()) {
      errorConstraintPositions.add(constraintPosition);
      return;
    }
    TypeConstructor typeConstructor = subjectType.getConstructor();
    List<TypeProjection> subjectArguments = subjectType.getArguments();
    List<TypeProjection> constrainingArguments = constrainingType.getArguments();
    List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
    for (int i = 0; i < subjectArguments.size(); i++) {
      Variance typeParameterVariance = parameters.get(i).getVariance();
      TypeProjection subjectArgument = subjectArguments.get(i);
      TypeProjection constrainingArgument = constrainingArguments.get(i);

      ConstraintKind typeParameterConstraintKind =
          getTypeParameterConstraintKind(
              typeParameterVariance, subjectArgument, constrainingArgument, constraintKind);

      addConstraint(
          typeParameterConstraintKind,
          subjectArgument.getType(),
          constrainingArgument.getType(),
          constraintPosition);
    }
  }
  protected Set<TypeElement> collectElements() {
    Set<TypeElement> elements = new HashSet<TypeElement>();

    // from delegate methods
    elements.addAll(processDelegateMethods());

    // from class annotations
    for (Class<? extends Annotation> annotation : conf.getEntityAnnotations()) {
      for (Element element : getElements(annotation)) {
        if (element instanceof TypeElement) {
          elements.add((TypeElement) element);
        }
      }
    }

    // from package annotations
    if (conf.getEntitiesAnnotation() != null) {
      for (Element element : getElements(conf.getEntitiesAnnotation())) {
        AnnotationMirror mirror =
            TypeUtils.getAnnotationMirrorOfType(element, conf.getEntitiesAnnotation());
        elements.addAll(TypeUtils.getAnnotationValuesAsElements(mirror, "value"));
      }
    }

    // from embedded annotations
    if (conf.getEmbeddedAnnotation() != null) {
      elements.addAll(getEmbeddedTypes());
    }

    // from embedded
    if (conf.isUnknownAsEmbedded()) {
      elements.addAll(getTypeFromProperties(elements));
    }

    // from annotation less supertypes
    elements.addAll(getAnnotationlessSupertypes(elements));

    // register possible embedded types of non-tracked supertypes
    if (conf.getEmbeddedAnnotation() != null) {
      Class<? extends Annotation> embedded = conf.getEmbeddedAnnotation();
      Set<TypeElement> embeddedElements = new HashSet<TypeElement>();
      for (TypeElement element : elements) {
        TypeMirror superTypeMirror = element.getSuperclass();
        while (superTypeMirror != null) {
          TypeElement superTypeElement =
              (TypeElement) processingEnv.getTypeUtils().asElement(superTypeMirror);
          if (superTypeElement != null) {
            List<? extends Element> enclosed = superTypeElement.getEnclosedElements();
            for (Element child : enclosed) {
              if (child.getAnnotation(embedded) != null) {
                handleEmbeddedType(child, embeddedElements);
              }
            }
            superTypeMirror = superTypeElement.getSuperclass();
            if (superTypeMirror instanceof NoType) {
              superTypeMirror = null;
            }
          } else {
            superTypeMirror = null;
          }
        }
      }

      // register found elements
      for (TypeElement element : embeddedElements) {
        if (!elements.contains(element)) {
          elementHandler.handleEntityType(element);
        }
      }
    }

    return elements;
  }
Exemple #21
0
class BulkBeanEmitter extends ClassEmitter {
    private static final Signature GET_PROPERTY_VALUES =
      TypeUtils.parseSignature("void getPropertyValues(Object, Object[])");
    private static final Signature SET_PROPERTY_VALUES =
      TypeUtils.parseSignature("void setPropertyValues(Object, Object[])");
    private static final Signature CSTRUCT_EXCEPTION =
      TypeUtils.parseConstructor("Throwable, int");
    private static final Type BULK_BEAN =
      TypeUtils.parseType("net.sf.cglib.beans.BulkBean");
    private static final Type BULK_BEAN_EXCEPTION =
      TypeUtils.parseType("net.sf.cglib.beans.BulkBeanException");
        
    public BulkBeanEmitter(ClassVisitor v,
                           String className,
                           Class target,
                           String[] getterNames,
                           String[] setterNames,
                           Class[] types) {
        super(v);

        Method[] getters = new Method[getterNames.length];
        Method[] setters = new Method[setterNames.length];
        validate(target, getterNames, setterNames, types, getters, setters);

        begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BULK_BEAN, null, Constants.SOURCE_FILE);
        EmitUtils.null_constructor(this);
        generateGet(target, getters);
        generateSet(target, setters);
        end_class();
    }

    private void generateGet(final Class target, final Method[] getters) {
        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_VALUES, null);
        if (getters.length >= 0) {
            e.load_arg(0);
            e.checkcast(Type.getType(target));
            Local bean = e.make_local();
            e.store_local(bean);
            for (int i = 0; i < getters.length; i++) {
                if (getters[i] != null) {
                    MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]);
                    e.load_arg(1);
                    e.push(i);
                    e.load_local(bean);
                    e.invoke(getter);
                    e.box(getter.getSignature().getReturnType());
                    e.aastore();
                }
            }
        }
        e.return_value();
        e.end_method();
    }

    private void generateSet(final Class target, final Method[] setters) {
        // setPropertyValues
        CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_PROPERTY_VALUES, null);
        if (setters.length > 0) {
            Local index = e.make_local(Type.INT_TYPE);
            e.push(0);
            e.store_local(index);
            e.load_arg(0);
            e.checkcast(Type.getType(target));
            e.load_arg(1);
            Block handler = e.begin_block();
            int lastIndex = 0;
            for (int i = 0; i < setters.length; i++) {
                if (setters[i] != null) {
                    MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]);
                    int diff = i - lastIndex;
                    if (diff > 0) {
                        e.iinc(index, diff);
                        lastIndex = i;
                    }
                    e.dup2();
                    e.aaload(i);
                    e.unbox(setter.getSignature().getArgumentTypes()[0]);
                    e.invoke(setter);
                }
            }
            handler.end();
            e.return_value();
            e.catch_exception(handler, Constants.TYPE_THROWABLE);
            e.new_instance(BULK_BEAN_EXCEPTION);
            e.dup_x1();
            e.swap();
            e.load_local(index);
            e.invoke_constructor(BULK_BEAN_EXCEPTION, CSTRUCT_EXCEPTION);
            e.athrow();
        } else {
            e.return_value();
        }
        e.end_method();
    }
    
    private static void validate(Class target,
                                 String[] getters,
                                 String[] setters,
                                 Class[] types,
                                 Method[] getters_out,
                                 Method[] setters_out) {
        int i = -1;
        if (setters.length != types.length || getters.length != types.length) {
            throw new BulkBeanException("accessor array length must be equal type array length", i);
        }
        try {
            for (i = 0; i < types.length; i++) {
                if (getters[i] != null) {
                    Method method = ReflectUtils.findDeclaredMethod(target, getters[i], null);
                    if (method.getReturnType() != types[i]) {
                        throw new BulkBeanException("Specified type " + types[i] +
                                                    " does not match declared type " + method.getReturnType(), i);
                    }
                    if (Modifier.isPrivate(method.getModifiers())) {
                        throw new BulkBeanException("Property is private", i);
                    }
                    getters_out[i] = method;
                }
                if (setters[i] != null) {
                    Method method = ReflectUtils.findDeclaredMethod(target, setters[i], new Class[]{ types[i] });
                    if (Modifier.isPrivate(method.getModifiers()) ){
                        throw new BulkBeanException("Property is private", i);
                    }
                    setters_out[i] = method;
                }
            }
        } catch (NoSuchMethodException e) {
            throw new BulkBeanException("Cannot find specified property", i);
        }
    }
}
 @NotNull
 public KotlinType getNullableNothingType() {
   return TypeUtils.makeNullable(getNothingType());
 }
  @NotNull
  private TypeProjection unsafeSubstitute(
      @NotNull TypeProjection originalProjection, int recursionDepth) throws SubstitutionException {
    assertRecursionDepth(recursionDepth, originalProjection, substitution);

    if (originalProjection.isStarProjection()) return originalProjection;

    // The type is within the substitution range, i.e. T or T?
    JetType type = originalProjection.getType();
    TypeProjection replacement = substitution.get(type);
    Variance originalProjectionKind = originalProjection.getProjectionKind();
    if (replacement == null
        && FlexibleTypesKt.isFlexible(type)
        && !TypeCapabilitiesKt.isCustomTypeVariable(type)) {
      Flexibility flexibility = FlexibleTypesKt.flexibility(type);
      TypeProjection substitutedLower =
          unsafeSubstitute(
              new TypeProjectionImpl(originalProjectionKind, flexibility.getLowerBound()),
              recursionDepth + 1);
      TypeProjection substitutedUpper =
          unsafeSubstitute(
              new TypeProjectionImpl(originalProjectionKind, flexibility.getUpperBound()),
              recursionDepth + 1);

      Variance substitutedProjectionKind = substitutedLower.getProjectionKind();
      assert (substitutedProjectionKind == substitutedUpper.getProjectionKind())
                  && originalProjectionKind == Variance.INVARIANT
              || originalProjectionKind == substitutedProjectionKind
          : "Unexpected substituted projection kind: "
              + substitutedProjectionKind
              + "; original: "
              + originalProjectionKind;

      JetType substitutedFlexibleType =
          DelegatingFlexibleType.create(
              substitutedLower.getType(),
              substitutedUpper.getType(),
              flexibility.getExtraCapabilities());
      return new TypeProjectionImpl(substitutedProjectionKind, substitutedFlexibleType);
    }

    if (KotlinBuiltIns.isNothing(type) || type.isError()) return originalProjection;

    if (replacement != null) {
      VarianceConflictType varianceConflict =
          conflictType(originalProjectionKind, replacement.getProjectionKind());

      // Captured type might be substituted in an opposite projection:
      // out 'Captured (in Int)' = out Int
      // in 'Captured (out Int)' = in Int
      boolean allowVarianceConflict = CapturedTypeConstructorKt.isCaptured(type);
      if (!allowVarianceConflict) {
        //noinspection EnumSwitchStatementWhichMissesCases
        switch (varianceConflict) {
          case OUT_IN_IN_POSITION:
            throw new SubstitutionException("Out-projection in in-position");
          case IN_IN_OUT_POSITION:
            // todo use the right type parameter variance and upper bound
            return new TypeProjectionImpl(
                Variance.OUT_VARIANCE, type.getConstructor().getBuiltIns().getNullableAnyType());
        }
      }
      JetType substitutedType;
      CustomTypeVariable typeVariable = TypeCapabilitiesKt.getCustomTypeVariable(type);
      if (replacement.isStarProjection()) {
        return replacement;
      } else if (typeVariable != null) {
        substitutedType = typeVariable.substitutionResult(replacement.getType());
      } else {
        // this is a simple type T or T?: if it's T, we should just take replacement, if T? - we
        // make replacement nullable
        substitutedType =
            TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable());
      }

      // substitutionType.annotations = replacement.annotations ++ type.annotations
      if (!type.getAnnotations().isEmpty()) {
        Annotations typeAnnotations = filterOutUnsafeVariance(type.getAnnotations());
        substitutedType =
            TypeUtilsKt.replaceAnnotations(
                substitutedType,
                new CompositeAnnotations(substitutedType.getAnnotations(), typeAnnotations));
      }

      Variance resultingProjectionKind =
          varianceConflict == VarianceConflictType.NO_CONFLICT
              ? combine(originalProjectionKind, replacement.getProjectionKind())
              : originalProjectionKind;
      return new TypeProjectionImpl(resultingProjectionKind, substitutedType);
    }
    // The type is not within the substitution range, i.e. Foo, Bar<T> etc.
    return substituteCompoundType(originalProjection, recursionDepth);
  }
 @NotNull
 public KotlinType getNullableAnyType() {
   return TypeUtils.makeNullable(getAnyType());
 }