예제 #1
0
  private static String getInlineName(
      @NotNull CodegenContext codegenContext,
      @NotNull DeclarationDescriptor currentDescriptor,
      @NotNull JetTypeMapper typeMapper,
      @NotNull JvmFileClassesProvider fileClassesProvider) {
    if (currentDescriptor instanceof PackageFragmentDescriptor) {
      PsiFile file = getContainingFile(codegenContext);

      Type implementationOwnerType;
      if (file == null) {
        implementationOwnerType =
            CodegenContextUtil.getImplementationOwnerClassType(codegenContext);
      } else {
        implementationOwnerType =
            FileClassesPackage.getFileClassType(fileClassesProvider, (JetFile) file);
      }

      if (implementationOwnerType == null) {
        DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor();
        //noinspection ConstantConditions
        throw new RuntimeException(
            "Couldn't find declaration for "
                + contextDescriptor.getContainingDeclaration().getName()
                + "."
                + contextDescriptor.getName()
                + "; context: "
                + codegenContext);
      }

      return implementationOwnerType.getInternalName();
    } else if (currentDescriptor instanceof ClassifierDescriptor) {
      Type type = typeMapper.mapType((ClassifierDescriptor) currentDescriptor);
      return type.getInternalName();
    } else if (currentDescriptor instanceof FunctionDescriptor) {
      ClassDescriptor descriptor =
          typeMapper
              .getBindingContext()
              .get(CodegenBinding.CLASS_FOR_CALLABLE, (FunctionDescriptor) currentDescriptor);
      if (descriptor != null) {
        Type type = typeMapper.mapType(descriptor);
        return type.getInternalName();
      }
    }

    // TODO: add suffix for special case
    String suffix =
        currentDescriptor.getName().isSpecial() ? "" : currentDescriptor.getName().asString();

    //noinspection ConstantConditions
    return getInlineName(
            codegenContext,
            currentDescriptor.getContainingDeclaration(),
            typeMapper,
            fileClassesProvider)
        + "$"
        + suffix;
  }
예제 #2
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());
  }