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)); } }
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()); } }); }
@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()]); }
@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(); }
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; } }
@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); } }
@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()]); }
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; }
@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; }