예제 #1
0
    private void reportCyclicInheritanceHierarchyError(
        @NotNull BindingTrace trace,
        @NotNull ClassDescriptor classDescriptor,
        @NotNull ClassDescriptor superclass) {
      PsiElement psiElement = DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor);

      PsiElement elementToMark = null;
      if (psiElement instanceof KtClassOrObject) {
        KtClassOrObject classOrObject = (KtClassOrObject) psiElement;
        for (KtSuperTypeListEntry delegationSpecifier : classOrObject.getSuperTypeListEntries()) {
          KtTypeReference typeReference = delegationSpecifier.getTypeReference();
          if (typeReference == null) continue;
          KotlinType supertype = trace.get(TYPE, typeReference);
          if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
            elementToMark = typeReference;
          }
        }
      }
      if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
        PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
        PsiElement nameIdentifier = namedElement.getNameIdentifier();
        if (nameIdentifier != null) {
          elementToMark = nameIdentifier;
        }
      }
      if (elementToMark != null) {
        trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
      }
    }
예제 #2
0
  public void genDelegate(
      @NotNull final FunctionDescriptor delegateFunction,
      final FunctionDescriptor delegatedTo,
      final ClassDescriptor toClass,
      final StackValue field) {
    generateMethod(
        JvmDeclarationOriginKt.Delegation(
            DescriptorToSourceUtils.descriptorToDeclaration(delegatedTo), delegateFunction),
        delegateFunction,
        new FunctionGenerationStrategy() {
          @Override
          public void generateBody(
              @NotNull MethodVisitor mv,
              @NotNull FrameMap frameMap,
              @NotNull JvmMethodSignature signature,
              @NotNull MethodContext context,
              @NotNull MemberCodegen<?> parentCodegen) {
            Method delegateToMethod =
                typeMapper.mapToCallableMethod(delegatedTo, /* superCall = */ false).getAsmMethod();
            Method delegateMethod = typeMapper.mapSignature(delegateFunction).getAsmMethod();

            Type[] argTypes = delegateMethod.getArgumentTypes();
            Type[] originalArgTypes = delegateToMethod.getArgumentTypes();

            InstructionAdapter iv = new InstructionAdapter(mv);
            iv.load(0, OBJECT_TYPE);
            field.put(field.type, iv);
            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();
            }

            String internalName = typeMapper.mapType(toClass).getInternalName();
            if (toClass.getKind() == ClassKind.INTERFACE) {
              iv.invokeinterface(
                  internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
            } else {
              iv.invokevirtual(
                  internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
            }

            StackValue stackValue =
                AsmUtil.genNotNullAssertions(
                    state,
                    StackValue.onStack(delegateToMethod.getReturnType()),
                    RuntimeAssertionInfo.create(
                        delegateFunction.getReturnType(),
                        delegatedTo.getReturnType(),
                        new RuntimeAssertionInfo.DataFlowExtras.OnlyMessage(
                            delegatedTo.getName() + "(...)")));

            stackValue.put(delegateMethod.getReturnType(), iv);

            iv.areturn(delegateMethod.getReturnType());
          }
        });
  }
예제 #3
0
  @Nullable
  private KtNamedDeclaration[] getVariables(Expression[] params, ExpressionContext context) {
    if (params.length != 0) return null;

    Project project = context.getProject();
    PsiDocumentManager.getInstance(project).commitAllDocuments();

    PsiFile psiFile =
        PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument());
    if (!(psiFile instanceof KtFile)) return null;

    KtExpression contextExpression = findContextExpression(psiFile, context.getStartOffset());
    if (contextExpression == null) return null;

    ResolutionFacade resolutionFacade = ResolutionUtils.getResolutionFacade(contextExpression);

    BindingContext bindingContext =
        resolutionFacade.analyze(contextExpression, BodyResolveMode.FULL);
    LexicalScope scope =
        ScopeUtils.getResolutionScope(contextExpression, bindingContext, resolutionFacade);

    IterableTypesDetector detector =
        resolutionFacade.getIdeService(IterableTypesDetection.class).createDetector(scope);

    DataFlowInfo dataFlowInfo =
        BindingContextUtilsKt.getDataFlowInfo(bindingContext, contextExpression);

    List<VariableDescriptor> filteredDescriptors = new ArrayList<VariableDescriptor>();
    for (DeclarationDescriptor declarationDescriptor : getAllVariables(scope)) {
      if (declarationDescriptor instanceof VariableDescriptor) {
        VariableDescriptor variableDescriptor = (VariableDescriptor) declarationDescriptor;

        if (variableDescriptor.getExtensionReceiverParameter() != null
            && ExtensionUtils.substituteExtensionIfCallableWithImplicitReceiver(
                    variableDescriptor, scope, bindingContext, dataFlowInfo)
                .isEmpty()) {
          continue;
        }

        if (isSuitable(variableDescriptor, project, detector)) {
          filteredDescriptors.add(variableDescriptor);
        }
      }
    }

    List<KtNamedDeclaration> declarations = new ArrayList<KtNamedDeclaration>();
    for (DeclarationDescriptor declarationDescriptor : filteredDescriptors) {
      PsiElement declaration =
          DescriptorToSourceUtils.descriptorToDeclaration(declarationDescriptor);
      assert declaration == null || declaration instanceof PsiNamedElement;

      if (declaration instanceof KtProperty || declaration instanceof KtParameter) {
        declarations.add((KtNamedDeclaration) declaration);
      }
    }

    return declarations.toArray(new KtNamedDeclaration[declarations.size()]);
  }
예제 #4
0
 @Nullable
 public static PsiFile getContainingFile(CodegenContext codegenContext) {
   DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor();
   PsiElement psiElement = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor);
   if (psiElement != null) {
     return psiElement.getContainingFile();
   }
   return null;
 }
  @Nullable
  public PsiElement resolveBuiltInSymbol(@NotNull DeclarationDescriptor declarationDescriptor) {
    if (moduleDescriptor == null) {
      return null;
    }

    DeclarationDescriptor descriptor = findCurrentDescriptor(declarationDescriptor);
    if (descriptor != null) {
      return DescriptorToSourceUtils.getSourceFromDescriptor(descriptor);
    }
    return null;
  }
  private static boolean checkIfHasExpectedType(
      @NotNull FunctionDescriptor functionDescriptor, boolean isInherited) {
    if (!(functionDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false;

    JetFunctionLiteral functionLiteral =
        (JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
    assert functionLiteral != null : "No declaration found for " + functionDescriptor;

    PsiElement parent = functionLiteral.getParent();
    if (!(parent instanceof JetFunctionLiteralExpression)) return false;

    JetFunctionLiteralExpression expression = (JetFunctionLiteralExpression) parent;
    return ResolvePackage.analyze(expression, BodyResolveMode.PARTIAL)
            .get(BindingContext.EXPECTED_EXPRESSION_TYPE, expression)
        != null;
  }
 private static String renderParameter(ValueParameterDescriptor parameter, boolean named) {
   StringBuilder builder = new StringBuilder();
   if (named) builder.append("[");
   if (parameter.getVarargElementType() != null) {
     builder.append("vararg ");
   }
   builder
       .append(parameter.getName())
       .append(": ")
       .append(
           DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(getActualParameterType(parameter)));
   if (DescriptorUtilPackage.hasDefaultValue(parameter)) {
     PsiElement parameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(parameter);
     builder.append(" = ").append(getDefaultExpressionString(parameterDeclaration));
   }
   if (named) builder.append("]");
   return builder.toString();
 }
예제 #8
0
 public ScriptContext(
     @NotNull JetTypeMapper typeMapper,
     @NotNull ScriptDescriptor scriptDescriptor,
     @NotNull List<ScriptDescriptor> earlierScripts,
     @NotNull ClassDescriptor contextDescriptor,
     @Nullable CodegenContext parentContext) {
   super(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null);
   this.scriptDescriptor = scriptDescriptor;
   this.earlierScripts = earlierScripts;
   KtScript script = (KtScript) DescriptorToSourceUtils.getSourceFromDescriptor(scriptDescriptor);
   assert script != null : "Declaration should be present for script: " + scriptDescriptor;
   KtDeclaration lastDeclaration = CollectionsKt.lastOrNull(script.getDeclarations());
   if (lastDeclaration instanceof KtAnonymousInitializer) {
     this.lastStatement = ((KtAnonymousInitializer) lastDeclaration).getBody();
   } else {
     this.lastStatement = null;
   }
 }
예제 #9
0
  @Override
  public void genCallInner(
      @NotNull Callable callableMethod,
      @Nullable ResolvedCall<?> resolvedCall,
      boolean callDefault,
      @NotNull ExpressionCodegen codegen) {
    SMAPAndMethodNode nodeAndSmap = null;
    if (!state.getInlineCycleReporter().enterIntoInlining(resolvedCall)) {
      generateStub(resolvedCall, codegen);
      return;
    }

    try {
      nodeAndSmap = createMethodNode(callDefault);
      endCall(inlineCall(nodeAndSmap));
    } catch (CompilationException e) {
      throw e;
    } catch (Exception e) {
      boolean generateNodeText = !(e instanceof InlineException);
      PsiElement element =
          DescriptorToSourceUtils.descriptorToDeclaration(
              this.codegen.getContext().getContextDescriptor());
      throw new CompilationException(
          "Couldn't inline method call '"
              + functionDescriptor.getName()
              + "' into \n"
              + (element != null
                  ? element.getText()
                  : "null psi element " + this.codegen.getContext().getContextDescriptor())
              + (generateNodeText
                  ? ("\ncause: "
                      + InlineCodegenUtil.getNodeText(
                          nodeAndSmap != null ? nodeAndSmap.getNode() : null))
                  : ""),
          e,
          callElement);
    } finally {
      state.getInlineCycleReporter().exitFromInliningOf(resolvedCall);
    }
  }
예제 #10
0
  @Nullable
  private static PsiNamedElement[] getSupertypes(Expression[] params, ExpressionContext context) {
    if (params.length != 0) return null;

    Project project = context.getProject();
    PsiDocumentManager.getInstance(project).commitAllDocuments();

    PsiFile psiFile =
        PsiDocumentManager.getInstance(project).getPsiFile(context.getEditor().getDocument());
    if (!(psiFile instanceof JetFile)) return null;

    JetExpression expression =
        PsiTreeUtil.getParentOfType(
            psiFile.findElementAt(context.getStartOffset()), JetExpression.class);
    if (expression == null) return null;

    BindingContext bc = ResolutionUtils.analyze(expression, BodyResolveMode.FULL);
    JetScope scope = bc.get(BindingContext.RESOLUTION_SCOPE, expression);
    if (scope == null) return null;

    List<PsiNamedElement> result = new ArrayList<PsiNamedElement>();

    for (DeclarationDescriptor descriptor :
        scope.getDescriptors(
            DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS,
            JetScope.Companion.getALL_NAME_FILTER())) {
      if (!(descriptor instanceof ClassDescriptor)) continue;
      ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
      if (!classDescriptor.getModality().isOverridable()) continue;
      ClassKind kind = classDescriptor.getKind();
      if (kind == ClassKind.INTERFACE || kind == ClassKind.CLASS) {
        PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
        if (declaration != null) {
          result.add((PsiNamedElement) declaration);
        }
      }
    }

    return result.toArray(new PsiNamedElement[result.size()]);
  }
예제 #11
0
  private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) {
    MethodNode node = nodeAndSmap.getNode();
    ReifiedTypeParametersUsages reificationResult =
        reifiedTypeInliner.reifyInstructions(node.instructions);
    generateClosuresBodies();

    // through generation captured parameters will be added to invocationParamBuilder
    putClosureParametersOnStack();

    addInlineMarker(codegen.v, true);

    Parameters parameters = invocationParamBuilder.buildParameters();

    InliningContext info =
        new RootInliningContext(
            expressionMap,
            state,
            codegen.getInlineNameGenerator().subGenerator(functionDescriptor.getName().asString()),
            codegen.getContext(),
            callElement,
            codegen.getParentCodegen().getClassName(),
            reifiedTypeInliner);

    MethodInliner inliner =
        new MethodInliner(
            node,
            parameters,
            info,
            new FieldRemapper(null, null, parameters),
            isSameModule,
            "Method inlining " + callElement.getText(),
            createNestedSourceMapper(nodeAndSmap)); // with captured

    LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);

    MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
    // hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain
    adapter.visitInsn(Opcodes.NOP);

    InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
    result.getReifiedTypeParametersUsages().mergeAll(reificationResult);

    CallableMemberDescriptor descriptor = codegen.getContext().getContextDescriptor();
    final Set<String> labels =
        getDeclarationLabels(
            DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor);
    LabelOwner labelOwner =
        new LabelOwner() {
          @Override
          public boolean isMyLabel(@NotNull String name) {
            return labels.contains(name);
          }
        };

    List<MethodInliner.PointForExternalFinallyBlocks> infos =
        MethodInliner.processReturns(adapter, labelOwner, true, null);
    generateAndInsertFinallyBlocks(
        adapter,
        infos,
        ((StackValue.Local) remapper.remap(parameters.totalSize() + 1).value).index);
    removeFinallyMarkers(adapter);

    adapter.accept(new InliningInstructionAdapter(codegen.v));

    addInlineMarker(codegen.v, false);

    return result;
  }
예제 #12
0
  @NotNull
  private SMAPAndMethodNode createMethodNode(boolean callDefault)
      throws ClassNotFoundException, IOException {
    JvmMethodSignature jvmSignature =
        typeMapper.mapSignature(functionDescriptor, context.getContextKind());

    Method asmMethod;
    if (callDefault) {
      asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
    } else {
      asmMethod = jvmSignature.getAsmMethod();
    }

    SMAPAndMethodNode nodeAndSMAP;
    if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
      JetTypeMapper.ContainingClassesInfo containingClasses =
          typeMapper.getContainingClassesForDeserializedCallable(
              (DeserializedSimpleFunctionDescriptor) functionDescriptor);

      VirtualFile file =
          InlineCodegenUtil.getVirtualFileForCallable(containingClasses.getImplClassId(), state);
      nodeAndSMAP =
          InlineCodegenUtil.getMethodNode(
              file.contentsToByteArray(),
              asmMethod.getName(),
              asmMethod.getDescriptor(),
              containingClasses.getFacadeClassId());

      if (nodeAndSMAP == null) {
        throw new RuntimeException(
            "Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
      }
    } else {
      PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);

      if (element == null || !(element instanceof JetNamedFunction)) {
        throw new RuntimeException(
            "Couldn't find declaration for function " + descriptorName(functionDescriptor));
      }
      JetNamedFunction inliningFunction = (JetNamedFunction) element;

      MethodNode node =
          new MethodNode(
              InlineCodegenUtil.API,
              getMethodAsmFlags(functionDescriptor, context.getContextKind())
                  | (callDefault ? Opcodes.ACC_STATIC : 0),
              asmMethod.getName(),
              asmMethod.getDescriptor(),
              jvmSignature.getGenericsSignature(),
              null);

      // for maxLocals calculation
      MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node);
      MethodContext methodContext = context.getParentContext().intoFunction(functionDescriptor);

      SMAP smap;
      if (callDefault) {
        Type implementationOwner = typeMapper.mapOwner(functionDescriptor);
        FakeMemberCodegen parentCodegen =
            new FakeMemberCodegen(
                codegen.getParentCodegen(),
                inliningFunction,
                (FieldOwnerContext) methodContext.getParentContext(),
                implementationOwner.getInternalName());
        FunctionCodegen.generateDefaultImplBody(
            methodContext,
            functionDescriptor,
            maxCalcAdapter,
            DefaultParameterValueLoader.DEFAULT,
            inliningFunction,
            parentCodegen);
        smap =
            createSMAPWithDefaultMapping(
                inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
      } else {
        smap =
            generateMethodBody(
                maxCalcAdapter,
                functionDescriptor,
                methodContext,
                inliningFunction,
                jvmSignature,
                false);
      }

      nodeAndSMAP = new SMAPAndMethodNode(node, smap);
      maxCalcAdapter.visitMaxs(-1, -1);
      maxCalcAdapter.visitEnd();
    }
    return nodeAndSMAP;
  }