Beispiel #1
0
  private void generateBridge(
      @Nullable PsiElement origin,
      @NotNull FunctionDescriptor descriptor,
      @NotNull Method bridge,
      @NotNull Method delegateTo,
      boolean isSpecialBridge,
      boolean isStubDeclarationWithDelegationToSuper) {
    boolean isSpecialOrDelegationToSuper =
        isSpecialBridge || isStubDeclarationWithDelegationToSuper;
    int flags =
        ACC_PUBLIC
            | ACC_BRIDGE
            | (!isSpecialOrDelegationToSuper ? ACC_SYNTHETIC : 0)
            | (isSpecialBridge ? ACC_FINAL : 0); // TODO.

    MethodVisitor mv =
        v.newMethod(
            JvmDeclarationOriginKt.Bridge(descriptor, origin),
            flags,
            bridge.getName(),
            bridge.getDescriptor(),
            null,
            null);
    if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;

    mv.visitCode();

    Type[] argTypes = bridge.getArgumentTypes();
    Type[] originalArgTypes = delegateTo.getArgumentTypes();

    InstructionAdapter iv = new InstructionAdapter(mv);
    MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);

    if (delegateTo.getArgumentTypes().length == 1 && isSpecialBridge) {
      generateTypeCheckBarrierIfNeeded(
          iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes()[0]);
    }

    iv.load(0, OBJECT_TYPE);
    for (int i = 0, reg = 1; i < argTypes.length; i++) {
      StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
      //noinspection AssignmentToForLoopParameter
      reg += argTypes[i].getSize();
    }

    if (isStubDeclarationWithDelegationToSuper) {
      ClassDescriptor parentClass =
          getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
      assert parentClass != null;
      String parentInternalName = typeMapper.mapClass(parentClass).getInternalName();
      iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor());
    } else {
      iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
    }

    StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
    iv.areturn(bridge.getReturnType());

    endVisit(mv, "bridge method", origin);
  }
Beispiel #2
0
  public static void genClosureFields(
      CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) {
    ClassifierDescriptor captureThis = closure.getCaptureThis();
    int access = NO_FLAG_PACKAGE_PRIVATE | ACC_SYNTHETIC | ACC_FINAL;
    if (captureThis != null) {
      v.newField(
          null,
          access,
          CAPTURED_THIS_FIELD,
          typeMapper.mapType(captureThis).getDescriptor(),
          null,
          null);
    }

    ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
    if (captureReceiver != null) {
      v.newField(
          null,
          access,
          CAPTURED_RECEIVER_FIELD,
          typeMapper.mapType(captureReceiver).getDescriptor(),
          null,
          null);
    }

    List<Pair<String, Type>> fields = closure.getRecordedFields();
    for (Pair<String, Type> field : fields) {
      v.newField(null, access, field.first, field.second.getDescriptor(), null, null);
    }
  }
Beispiel #3
0
  @NotNull
  protected ExpressionCodegen createOrGetClInitCodegen() {
    DeclarationDescriptor descriptor = context.getContextDescriptor();
    assert state.getClassBuilderMode() == ClassBuilderMode.FULL
        : "<clinit> should not be generated for light classes. Descriptor: " + descriptor;
    if (clInit == null) {
      MethodVisitor mv = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
      mv.visitCode();
      SimpleFunctionDescriptorImpl clInit =
          SimpleFunctionDescriptorImpl.create(
              descriptor, Annotations.EMPTY, Name.special("<clinit>"), SYNTHESIZED);
      clInit.initialize(
          null,
          null,
          Collections.<TypeParameterDescriptor>emptyList(),
          Collections.<ValueParameterDescriptor>emptyList(),
          null,
          null,
          Visibilities.PRIVATE);

      this.clInit =
          new ExpressionCodegen(
              mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
    }
    return clInit;
  }
Beispiel #4
0
  void generateDefaultIfNeeded(
      @NotNull MethodContext owner,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull OwnerKind kind,
      @NotNull DefaultParameterValueLoader loadStrategy,
      @Nullable KtNamedFunction function) {
    DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();

    if (kind != OwnerKind.DEFAULT_IMPLS && isInterface(contextClass)) {
      return;
    }

    if (!isDefaultNeeded(functionDescriptor)) {
      return;
    }

    int flags =
        getVisibilityAccessFlag(functionDescriptor)
            | getDeprecatedAccessFlag(functionDescriptor)
            | ACC_SYNTHETIC;
    if (!(functionDescriptor instanceof ConstructorDescriptor)) {
      flags |= ACC_STATIC | ACC_BRIDGE;
    }
    // $default methods are never private to be accessible from other class files (e.g. inner)
    // without the need of synthetic accessors
    flags &= ~ACC_PRIVATE;

    Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);

    MethodVisitor mv =
        v.newMethod(
            JvmDeclarationOriginKt.Synthetic(function, functionDescriptor),
            flags,
            defaultMethod.getName(),
            defaultMethod.getDescriptor(),
            null,
            getThrownExceptions(functionDescriptor, typeMapper));

    // Only method annotations are copied to the $default method. Parameter annotations are not
    // copied until there are valid use cases;
    // enum constructors have two additional synthetic parameters which somewhat complicate this
    // task
    AnnotationCodegen.forMethod(mv, typeMapper)
        .genAnnotations(functionDescriptor, defaultMethod.getReturnType());

    if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
      if (this.owner instanceof MultifileClassFacadeContext) {
        mv.visitCode();
        generateFacadeDelegateMethodBody(
            mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
        endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
      } else {
        mv.visitCode();
        generateDefaultImplBody(
            owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
        endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
      }
    }
  }
Beispiel #5
0
  private void done() {
    if (clInit != null) {
      clInit.v.visitInsn(RETURN);
      FunctionCodegen.endVisit(clInit.v, "static initializer", element);
    }

    v.done();
  }
        @Override
        public String asText(ClassBuilder builder) {
          TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor();

          StringWriter writer = new StringWriter();
          visitor.p.print(new PrintWriter(writer));

          return writer.toString();
        }
  private void generateParameterAnnotations(
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodVisitor mv,
      @NotNull JvmMethodSignature jvmSignature) {
    Iterator<ValueParameterDescriptor> iterator =
        functionDescriptor.getValueParameters().iterator();
    List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();

    for (int i = 0; i < kotlinParameterTypes.size(); i++) {
      JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
      JvmMethodParameterKind kind = parameterSignature.getKind();
      if (kind.isSkippedInGenericSignature()) {
        markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
        continue;
      }

      if (kind == JvmMethodParameterKind.VALUE) {
        ValueParameterDescriptor parameter = iterator.next();
        if (parameter.getIndex() != i) {
          v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
        }
        AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);

        if (functionDescriptor instanceof PropertySetterDescriptor) {
          PropertyDescriptor propertyDescriptor =
              ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
          Annotated targetedAnnotations =
              new AnnotatedWithOnlyTargetedAnnotations(propertyDescriptor);
          annotationCodegen.genAnnotations(
              targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
        }

        if (functionDescriptor instanceof ConstructorDescriptor) {
          annotationCodegen.genAnnotations(
              parameter, parameterSignature.getAsmType(), CONSTRUCTOR_PARAMETER);
        } else {
          annotationCodegen.genAnnotations(parameter, parameterSignature.getAsmType());
        }
      } else if (kind == JvmMethodParameterKind.RECEIVER) {
        ReceiverParameterDescriptor receiver =
            ((functionDescriptor instanceof PropertyAccessorDescriptor)
                    ? ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty()
                    : functionDescriptor)
                .getExtensionReceiverParameter();
        if (receiver != null) {
          AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
          Annotated targetedAnnotations =
              new AnnotatedWithOnlyTargetedAnnotations(receiver.getType());
          annotationCodegen.genAnnotations(
              targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
        }
      }
    }
  }
 private void generateRemoveInIterator() {
   // generates stub 'remove' function for subclasses of Iterator to be compatible with
   // java.util.Iterator
   if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
     MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "remove", "()V", null, null);
     genMethodThrow(
         mv,
         "java/lang/UnsupportedOperationException",
         "Mutating method called on a Kotlin Iterator");
   }
 }
  private void generateStaticInitializer() {
    if (staticInitializerChunks.size() > 0) {
      MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
      if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
        mv.visitCode();

        InstructionAdapter v = new InstructionAdapter(mv);

        for (CodeChunk chunk : staticInitializerChunks) {
          chunk.generate(v);
        }

        mv.visitInsn(RETURN);
        FunctionCodegen.endVisit(v, "static initializer", myClass);
      }
    }
  }
  @Override
  public Result compile(Scope outer) throws Exception {
    if (!compile.compareAndSet(false, true)) {
      Result result = builder.compile(outer);
      Type type = result.getValue();

      collector.update(constants); // collect static constants first

      for (TypePart part : parts) {
        Initializer initializer = part.compile(collector, type);
        collector.update(initializer);
      }
      generator.generate(type);

      return result;
    }
    return ResultType.getNormal();
  }
Beispiel #11
0
  protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
    List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
    for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
      if (declaration instanceof JetProperty) {
        JetProperty property = (JetProperty) declaration;
        if (property.getDelegate() != null) {
          delegatedProperties.add(property);
        }
      }
    }
    if (delegatedProperties.isEmpty()) return;

    v.newField(
        null,
        ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC,
        JvmAbi.PROPERTY_METADATA_ARRAY_NAME,
        "[" + PROPERTY_METADATA_TYPE,
        null,
        null);

    InstructionAdapter iv = createOrGetClInitCodegen().v;
    iv.iconst(delegatedProperties.size());
    iv.newarray(PROPERTY_METADATA_TYPE);

    for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
      VariableDescriptor property =
          BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));

      iv.dup();
      iv.iconst(i);
      iv.anew(PROPERTY_METADATA_IMPL_TYPE);
      iv.dup();
      iv.visitLdcInsn(property.getName().asString());
      iv.invokespecial(
          PROPERTY_METADATA_IMPL_TYPE.getInternalName(), "<init>", "(Ljava/lang/String;)V");
      iv.astore(PROPERTY_METADATA_IMPL_TYPE);
    }

    iv.putstatic(
        thisAsmType.getInternalName(),
        JvmAbi.PROPERTY_METADATA_ARRAY_NAME,
        "[" + PROPERTY_METADATA_TYPE);
  }
 private void generatePrimaryConstructorProperties(
     PropertyCodegen propertyCodegen, JetClassOrObject origin) {
   boolean isAnnotation = origin instanceof JetClass && ((JetClass) origin).isAnnotation();
   for (JetParameter p : getPrimaryConstructorParameters()) {
     if (p.getValOrVarNode() != null) {
       PropertyDescriptor propertyDescriptor =
           state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
       if (propertyDescriptor != null) {
         if (!isAnnotation) {
           propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor);
         } else {
           Type type = state.getTypeMapper().mapType(propertyDescriptor);
           v.newMethod(
               p, ACC_PUBLIC | ACC_ABSTRACT, p.getName(), "()" + type.getDescriptor(), null, null);
         }
       }
     }
   }
 }
Beispiel #13
0
  private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) {
    if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
      DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
      if (CodegenUtil.isInterface(containingDeclaration)) return;

      Object value = null;
      final JetExpression initializer = p.getInitializer();
      if (initializer != null) {
        if (initializer instanceof JetConstantExpression) {
          CompileTimeConstant<?> compileTimeValue =
              state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
          value = compileTimeValue != null ? compileTimeValue.getValue() : null;
        }
      }
      int modifiers;
      if (kind == OwnerKind.NAMESPACE) {
        int access = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0);
        modifiers = access | Opcodes.ACC_STATIC;
      } else {
        modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0);
      }
      if (!propertyDescriptor.isVar()) {
        modifiers |= Opcodes.ACC_FINAL;
      }
      if (state.getInjector().getJetStandardLibrary().isVolatile(propertyDescriptor)) {
        modifiers |= Opcodes.ACC_VOLATILE;
      }
      Type type =
          state
              .getInjector()
              .getJetTypeMapper()
              .mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
      FieldVisitor fieldVisitor =
          v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, value);
      AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper())
          .genAnnotations(propertyDescriptor);
    }
  }
Beispiel #14
0
  public void generateBridges(@NotNull FunctionDescriptor descriptor) {
    if (descriptor instanceof ConstructorDescriptor) return;
    if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
    if (isInterface(descriptor.getContainingDeclaration())) return;

    // equals(Any?), hashCode(), toString() never need bridges
    if (isMethodOfAny(descriptor)) return;

    // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter
    // or alike and doesn't need bridges
    if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return;

    boolean isSpecial =
        SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null;

    Set<Bridge<Method>> bridgesToGenerate;
    if (!isSpecial) {
      bridgesToGenerate =
          ImplKt.generateBridgesForFunctionDescriptor(descriptor, getSignatureMapper(typeMapper));
      if (!bridgesToGenerate.isEmpty()) {
        PsiElement origin =
            descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
        boolean isSpecialBridge =
            BuiltinMethodsWithSpecialGenericSignature
                    .getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor)
                != null;

        for (Bridge<Method> bridge : bridgesToGenerate) {
          generateBridge(
              origin, descriptor, bridge.getFrom(), bridge.getTo(), isSpecialBridge, false);
        }
      }
    } else {
      Set<BridgeForBuiltinSpecial<Method>> specials =
          BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
              descriptor, getSignatureMapper(typeMapper));

      if (!specials.isEmpty()) {
        PsiElement origin =
            descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
        for (BridgeForBuiltinSpecial<Method> bridge : specials) {
          generateBridge(
              origin,
              descriptor,
              bridge.getFrom(),
              bridge.getTo(),
              bridge.isSpecial(),
              bridge.isDelegateToSuper());
        }
      }

      if (!descriptor.getKind().isReal()
          && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
        CallableDescriptor overridden =
            SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
        assert overridden != null;

        Method method = typeMapper.mapSignature(descriptor).getAsmMethod();
        int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor);
        v.newMethod(
            JvmDeclarationOriginKt.OtherOrigin(overridden),
            flags,
            method.getName(),
            method.getDescriptor(),
            null,
            null);
      }
    }
  }
  private <T> Class<? extends T> generateUnderLock(Class<T> type) {
    Map<Class<?>, Class<?>> cache = GENERATED_CLASSES.get(getClass());
    if (cache == null) {
      // WeakHashMap won't work here. It keeps a strong reference to the mapping value, which is the
      // generated class in this case
      // However, the generated class has a strong reference to the source class (by extending it),
      // so the keys will always be
      // strongly reachable while this Class is strongly reachable. Use weak references for both key
      // and value of the mapping instead.
      cache = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK);
      GENERATED_CLASSES.put(getClass(), cache);
    }
    Class<?> generatedClass = cache.get(type);
    if (generatedClass != null) {
      return generatedClass.asSubclass(type);
    }

    if (Modifier.isPrivate(type.getModifiers())) {
      throw new GradleException(
          String.format(
              "Cannot create a proxy class for private class '%s'.", type.getSimpleName()));
    }
    if (Modifier.isAbstract(type.getModifiers())) {
      throw new GradleException(
          String.format(
              "Cannot create a proxy class for abstract class '%s'.", type.getSimpleName()));
    }

    Class<? extends T> subclass;
    try {
      ClassMetaData classMetaData = inspectType(type);

      ClassBuilder<T> builder = start(type, classMetaData);

      builder.startClass();

      if (!DynamicObjectAware.class.isAssignableFrom(type)) {
        if (ExtensionAware.class.isAssignableFrom(type)) {
          throw new UnsupportedOperationException(
              "A type that implements ExtensionAware must currently also implement DynamicObjectAware.");
        }
        builder.mixInDynamicAware();
      }
      if (!GroovyObject.class.isAssignableFrom(type)) {
        builder.mixInGroovyObject();
      }
      builder.addDynamicMethods();
      if (classMetaData.conventionAware && !IConventionAware.class.isAssignableFrom(type)) {
        builder.mixInConventionAware();
      }

      Class noMappingClass = Object.class;
      for (Class<?> c = type; c != null && noMappingClass == Object.class; c = c.getSuperclass()) {
        if (c.getAnnotation(NoConventionMapping.class) != null) {
          noMappingClass = c;
        }
      }

      Set<PropertyMetaData> conventionProperties = new HashSet<PropertyMetaData>();

      for (PropertyMetaData property : classMetaData.properties.values()) {
        if (SKIP_PROPERTIES.contains(property.name)) {
          continue;
        }

        if (property.injector) {
          builder.addInjectorProperty(property);
          for (Method getter : property.getters) {
            builder.applyServiceInjectionToGetter(property, getter);
          }
          for (Method setter : property.setters) {
            builder.applyServiceInjectionToSetter(property, setter);
          }
          continue;
        }

        boolean needsConventionMapping = false;
        if (classMetaData.isExtensible()) {
          for (Method getter : property.getters) {
            if (!Modifier.isFinal(getter.getModifiers())
                && !getter.getDeclaringClass().isAssignableFrom(noMappingClass)) {
              needsConventionMapping = true;
              break;
            }
          }
        }

        if (needsConventionMapping) {
          conventionProperties.add(property);
          builder.addConventionProperty(property);
          for (Method getter : property.getters) {
            builder.applyConventionMappingToGetter(property, getter);
          }
        }

        if (needsConventionMapping) {
          for (Method setter : property.setters) {
            if (!Modifier.isFinal(setter.getModifiers())) {
              builder.applyConventionMappingToSetter(property, setter);
            }
          }
        }
      }

      Set<Method> actionMethods = classMetaData.missingOverloads;
      for (Method method : actionMethods) {
        builder.addActionMethod(method);
      }

      // Adds a set method for each mutable property
      for (PropertyMetaData property : classMetaData.properties.values()) {
        if (property.setters.isEmpty()) {
          continue;
        }
        if (Iterable.class.isAssignableFrom(property.getType())) {
          // Currently not supported
          continue;
        }

        if (property.setMethods.isEmpty()) {
          for (Method setter : property.setters) {
            builder.addSetMethod(property, setter);
          }
        } else if (conventionProperties.contains(property)) {
          for (Method setMethod : property.setMethods) {
            builder.applyConventionMappingToSetMethod(property, setMethod);
          }
        }
      }

      for (Constructor<?> constructor : type.getConstructors()) {
        if (Modifier.isPublic(constructor.getModifiers())) {
          builder.addConstructor(constructor);
        }
      }

      subclass = builder.generate();
    } catch (Throwable e) {
      throw new GradleException(
          String.format("Could not generate a proxy class for class %s.", type.getName()), e);
    }

    cache.put(type, subclass);
    cache.put(subclass, subclass);
    return subclass;
  }
Beispiel #16
0
 @Override
 public byte[] asBytes(ClassBuilder builder) {
   ClassWriter visitor = (ClassWriter) builder.getVisitor();
   return visitor.toByteArray();
 }
  public <T> Class<? extends T> generate(Class<T> type) {
    Map<Class, Class> cache = GENERATED_CLASSES.get(getClass());
    if (cache == null) {
      cache = new HashMap<Class, Class>();
      GENERATED_CLASSES.put(getClass(), cache);
    }
    Class generatedClass = cache.get(type);
    if (generatedClass != null) {
      return generatedClass;
    }

    if (Modifier.isPrivate(type.getModifiers())) {
      throw new GradleException(
          String.format(
              "Cannot create a proxy class for private class '%s'.", type.getSimpleName()));
    }
    if (Modifier.isAbstract(type.getModifiers())) {
      throw new GradleException(
          String.format(
              "Cannot create a proxy class for abstract class '%s'.", type.getSimpleName()));
    }

    Class<? extends T> subclass;
    try {
      ClassBuilder<T> builder = start(type);

      boolean isConventionAware = type.getAnnotation(NoConventionMapping.class) == null;
      boolean isDynamicAware = type.getAnnotation(NoDynamicObject.class) == null;

      builder.startClass(isConventionAware, isDynamicAware);

      if (isDynamicAware && !DynamicObjectAware.class.isAssignableFrom(type)) {
        builder.mixInDynamicAware();
      }
      if (isDynamicAware && !GroovyObject.class.isAssignableFrom(type)) {
        builder.mixInGroovyObject();
      }
      if (isDynamicAware) {
        builder.addDynamicMethods();
      }
      if (isConventionAware && !IConventionAware.class.isAssignableFrom(type)) {
        builder.mixInConventionAware();
      }

      Class noMappingClass = Object.class;
      for (Class<?> c = type; c != null && noMappingClass == Object.class; c = c.getSuperclass()) {
        if (c.getAnnotation(NoConventionMapping.class) != null) {
          noMappingClass = c;
        }
      }

      Collection<String> skipProperties =
          Arrays.asList("metaClass", "conventionMapping", "convention", "asDynamicObject");

      MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(type);
      for (MetaProperty property : metaClass.getProperties()) {
        if (skipProperties.contains(property.getName())) {
          continue;
        }
        if (property instanceof MetaBeanProperty) {
          MetaBeanProperty metaBeanProperty = (MetaBeanProperty) property;
          MetaMethod getter = metaBeanProperty.getGetter();
          if (getter == null) {
            continue;
          }
          if (Modifier.isFinal(getter.getModifiers())
              || Modifier.isPrivate(getter.getModifiers())) {
            continue;
          }
          if (getter.getReturnType().isPrimitive()) {
            continue;
          }
          Class declaringClass = getter.getDeclaringClass().getTheClass();
          if (declaringClass.isAssignableFrom(noMappingClass)) {
            continue;
          }
          builder.addGetter(metaBeanProperty);

          MetaMethod setter = metaBeanProperty.getSetter();
          if (setter == null) {
            continue;
          }
          if (Modifier.isFinal(setter.getModifiers())
              || Modifier.isPrivate(setter.getModifiers())) {
            continue;
          }

          builder.addSetter(metaBeanProperty);
        }
      }

      for (Constructor<?> constructor : type.getConstructors()) {
        if (Modifier.isPublic(constructor.getModifiers())) {
          builder.addConstructor(constructor);
        }
      }

      subclass = builder.generate();
    } catch (Throwable e) {
      throw new GradleException(
          String.format("Could not generate a proxy class for class %s.", type.getName()), e);
    }

    cache.put(type, subclass);
    return subclass;
  }
 @Override
 public Result define(Scope outer) throws Exception {
   return builder.define(outer);
 }
Beispiel #19
0
  public void generateDefaultSetter(
      PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
    if (propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
      throw new IllegalStateException("must not generate code for fake overrides");
    }

    if (kind == OwnerKind.TRAIT_IMPL) {
      return;
    }

    if (kind == OwnerKind.NAMESPACE) {
      flags |= Opcodes.ACC_STATIC;
    }

    PsiElement psiElement =
        state
            .getBindingContext()
            .get(
                BindingContext.DESCRIPTOR_TO_DECLARATION,
                propertyDescriptor.getContainingDeclaration());
    boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait();
    if (isTrait && !(kind instanceof OwnerKind.DelegateKind)) flags |= Opcodes.ACC_ABSTRACT;

    if (propertyDescriptor.getModality() == Modality.FINAL) {
      flags |= Opcodes.ACC_FINAL;
    }

    JvmPropertyAccessorSignature signature =
        state.getInjector().getJetTypeMapper().mapSetterSignature(propertyDescriptor, kind);
    final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor();
    MethodVisitor mv =
        v.newMethod(
            origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null);
    generateJetPropertyAnnotation(
        mv,
        signature.getPropertyTypeKotlinSignature(),
        signature.getJvmMethodSignature().getKotlinTypeParameter());

    if (propertyDescriptor.getSetter() != null) {
      assert !propertyDescriptor.getSetter().hasBody();
      AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper())
          .genAnnotations(propertyDescriptor.getSetter());
    }

    if (v.generateCode() != ClassBuilder.Mode.SIGNATURES
        && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
      if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
        mv.visitCode();
        if (v.generateCode() == ClassBuilder.Mode.STUBS) {
          StubCodegen.generateStubThrow(mv);
        } else {
          InstructionAdapter iv = new InstructionAdapter(mv);
          final Type type =
              state
                  .getInjector()
                  .getJetTypeMapper()
                  .mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
          int paramCode = 0;
          if (kind != OwnerKind.NAMESPACE) {
            iv.load(0, JetTypeMapper.TYPE_OBJECT);
            paramCode = 1;
          }

          if ((kind instanceof OwnerKind.DelegateKind)
              != (propertyDescriptor.getKind() == FunctionDescriptor.Kind.DELEGATION)) {
            throw new IllegalStateException("mismatching kind in " + propertyDescriptor);
          }

          if (kind instanceof OwnerKind.DelegateKind) {
            OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
            iv.load(0, JetTypeMapper.TYPE_OBJECT);
            dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);

            iv.load(paramCode, type);
            iv.invokeinterface(
                dk.getOwnerClass(), setterName(propertyDescriptor.getName()), descriptor);
          } else {
            iv.load(paramCode, type);
            iv.visitFieldInsn(
                kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD,
                state.getInjector().getJetTypeMapper().getOwner(propertyDescriptor, kind),
                propertyDescriptor.getName(),
                type.getDescriptor());
          }

          iv.visitInsn(Opcodes.RETURN);
        }
      }
      FunctionCodegen.endVisit(mv, "setter", origin);
    }
  }
Beispiel #20
0
  public void generateMethod(
      @NotNull JvmDeclarationOrigin origin,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodContext methodContext,
      @NotNull FunctionGenerationStrategy strategy) {
    OwnerKind contextKind = methodContext.getContextKind();
    if (isInterface(functionDescriptor.getContainingDeclaration())
        && functionDescriptor.getVisibility() == Visibilities.PRIVATE
        && contextKind != OwnerKind.DEFAULT_IMPLS) {
      return;
    }

    JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, contextKind);
    Method asmMethod = jvmSignature.getAsmMethod();

    int flags = getMethodAsmFlags(functionDescriptor, contextKind);
    boolean isNative = NativeKt.hasNativeAnnotation(functionDescriptor);

    if (isNative && owner instanceof MultifileClassFacadeContext) {
      // Native methods are only defined in facades and do not need package part implementations
      return;
    }
    MethodVisitor mv =
        v.newMethod(
            origin,
            flags,
            asmMethod.getName(),
            asmMethod.getDescriptor(),
            jvmSignature.getGenericsSignature(),
            getThrownExceptions(functionDescriptor, typeMapper));

    if (CodegenContextUtil.isImplClassOwner(owner)) {
      v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
    }

    generateMethodAnnotations(functionDescriptor, asmMethod, mv);

    generateParameterAnnotations(
        functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));

    generateBridges(functionDescriptor);

    boolean staticInCompanionObject =
        AnnotationUtilKt.isPlatformStaticInCompanionObject(functionDescriptor);
    if (staticInCompanionObject) {
      ImplementationBodyCodegen parentBodyCodegen =
          (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
      parentBodyCodegen.addAdditionalTask(
          new JvmStaticGenerator(functionDescriptor, origin, state));
    }

    if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES
        || isAbstractMethod(functionDescriptor, contextKind)) {
      generateLocalVariableTable(
          mv,
          jvmSignature,
          functionDescriptor,
          getThisTypeForFunction(functionDescriptor, methodContext, typeMapper),
          new Label(),
          new Label(),
          contextKind);

      mv.visitEnd();
      return;
    }

    if (!isNative) {
      generateMethodBody(
          mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
    } else if (staticInCompanionObject) {
      // native @JvmStatic foo() in companion object should delegate to the static native function
      // moved to the outer class
      mv.visitCode();
      FunctionDescriptor staticFunctionDescriptor =
          JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
      JvmMethodSignature jvmMethodSignature =
          typeMapper.mapSignature(
              memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
      Type owningType =
          typeMapper.mapClass(
              (ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
      generateDelegateToMethodBody(
          false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName());
    }

    endVisit(mv, null, origin.getElement());
  }