public void process(@NotNull BodiesResolveContext bodiesResolveContext) { for (JetFile file : bodiesResolveContext.getFiles()) { checkDeclarationContainer(file); } for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) { if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue; checkDeclarationContainer(aClass); } for (JetObjectDeclaration objectDeclaration : bodiesResolveContext.getObjects().keySet()) { if (!bodiesResolveContext.completeAnalysisNeeded(objectDeclaration)) continue; checkDeclarationContainer(objectDeclaration); } for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : bodiesResolveContext.getFunctions().entrySet()) { JetNamedFunction function = entry.getKey(); SimpleFunctionDescriptor functionDescriptor = entry.getValue(); if (!bodiesResolveContext.completeAnalysisNeeded(function)) continue; final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType() ? NO_EXPECTED_TYPE : functionDescriptor.getReturnType(); checkFunction(function, expectedReturnType); } for (Map.Entry<JetProperty, PropertyDescriptor> entry : bodiesResolveContext.getProperties().entrySet()) { JetProperty property = entry.getKey(); if (!bodiesResolveContext.completeAnalysisNeeded(property)) continue; PropertyDescriptor propertyDescriptor = entry.getValue(); checkProperty(property, propertyDescriptor); } }
@Override public void processQuery( @NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull Processor<PsiReference> consumer) { PsiElement element = queryParameters.getElementToSearch(); if (element instanceof JetClass) { processJetClassOrObject((JetClass) element, queryParameters); } else if (element instanceof JetNamedFunction) { final JetNamedFunction function = (JetNamedFunction) element; String name = function.getName(); if (name != null) { PsiMethod method = ApplicationManager.getApplication() .runReadAction( new Computable<PsiMethod>() { @Override public PsiMethod compute() { return LightClassUtil.getLightClassMethod(function); } }); searchMethod(queryParameters, method); } } else if (element instanceof JetProperty) { final JetProperty property = (JetProperty) element; LightClassUtil.PropertyAccessorsPsiMethods propertyMethods = ApplicationManager.getApplication() .runReadAction( new Computable<LightClassUtil.PropertyAccessorsPsiMethods>() { @Override public LightClassUtil.PropertyAccessorsPsiMethods compute() { return LightClassUtil.getLightClassPropertyMethods(property); } }); searchMethod(queryParameters, propertyMethods.getGetter()); searchMethod(queryParameters, propertyMethods.getSetter()); } else if (element instanceof JetObjectDeclarationName) { PsiElement parent = element.getParent(); if (parent instanceof JetObjectDeclaration) { processJetClassOrObject((JetObjectDeclaration) parent, queryParameters); } } }
@Override public void visitNamedFunction(JetNamedFunction function) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); // working around a problem with shallow analysis if (functionDescriptor == null) return; DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); if (containingDeclaration instanceof ClassDescriptor) { nameStack.push(peekFromStack(nameStack) + '$' + function.getName()); super.visitNamedFunction(function); nameStack.pop(); } else if (containingDeclaration instanceof NamespaceDescriptor) { String peek = peekFromStack(nameStack); if (peek.isEmpty()) { peek = JvmAbi.PACKAGE_CLASS; } else { peek += "/" + JvmAbi.PACKAGE_CLASS; } nameStack.push(peek + '$' + function.getName()); super.visitNamedFunction(function); nameStack.pop(); } else { String name = inventAnonymousClassName(function); ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor); recordClosure( bindingTrace, function, classDescriptor, peekFromStack(classStack), JvmClassName.byInternalName(name), true); classStack.push(classDescriptor); nameStack.push(name); super.visitNamedFunction(function); nameStack.pop(); classStack.pop(); } }
public AlternativeMethodSignatureData( @NotNull ExternalAnnotationResolver externalAnnotationResolver, @NotNull JavaMethod method, @Nullable JetType receiverType, @NotNull Project project, @NotNull List<ValueParameterDescriptor> valueParameters, @Nullable JetType originalReturnType, @NotNull List<TypeParameterDescriptor> methodTypeParameters, boolean hasSuperMethods) { String signature = SignaturesUtil.getKotlinSignature(externalAnnotationResolver, method); if (signature == null) { setAnnotated(false); altFunDeclaration = null; return; } if (receiverType != null) { throw new UnsupportedOperationException( "Alternative annotations for extension functions are not supported yet"); } setAnnotated(true); altFunDeclaration = JetPsiFactory.createFunction(project, signature); originalToAltTypeParameters = DescriptorResolverUtils.recreateTypeParametersAndReturnMapping(methodTypeParameters, null); try { checkForSyntaxErrors(altFunDeclaration); checkEqualFunctionNames(altFunDeclaration, method); computeTypeParameters(methodTypeParameters); computeValueParameters(valueParameters); if (originalReturnType != null) { altReturnType = computeReturnType( originalReturnType, altFunDeclaration.getReturnTypeRef(), originalToAltTypeParameters); } if (hasSuperMethods) { checkParameterAndReturnTypesForOverridingMethods( valueParameters, methodTypeParameters, originalReturnType); } } catch (AlternativeSignatureMismatchException e) { setError(e.getMessage()); } }
private void computeTypeParameters(List<TypeParameterDescriptor> typeParameters) { if (typeParameters.size() != altFunDeclaration.getTypeParameters().size()) { throw new AlternativeSignatureMismatchException( "Method signature has %d type parameters, but alternative signature has %d", typeParameters.size(), altFunDeclaration.getTypeParameters().size()); } altTypeParameters = new ArrayList<TypeParameterDescriptor>(); for (int i = 0, size = typeParameters.size(); i < size; i++) { TypeParameterDescriptor originalTypeParamDescriptor = typeParameters.get(i); TypeParameterDescriptorImpl altParamDescriptor = originalToAltTypeParameters.get(originalTypeParamDescriptor); JetTypeParameter altTypeParameter = altFunDeclaration.getTypeParameters().get(i); int upperBoundIndex = 0; for (JetType upperBound : originalTypeParamDescriptor.getUpperBounds()) { JetTypeElement altTypeElement; if (upperBoundIndex == 0) { JetTypeReference extendsBound = altTypeParameter.getExtendsBound(); if (extendsBound == null) { // default upper bound assert originalTypeParamDescriptor.getUpperBounds().size() == 1; altParamDescriptor.addDefaultUpperBound(); break; } else { altTypeElement = extendsBound.getTypeElement(); } } else { JetTypeConstraint constraint = findTypeParameterConstraint( altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex); if (constraint == null) { throw new AlternativeSignatureMismatchException( "Upper bound #%d for type parameter %s is missing", upperBoundIndex, originalTypeParamDescriptor.getName()); } //noinspection ConstantConditions altTypeElement = constraint.getBoundTypeReference().getTypeElement(); } assert (altTypeElement != null); altParamDescriptor.addUpperBound( TypeTransformingVisitor.computeType( altTypeElement, upperBound, originalToAltTypeParameters, UPPER_BOUND)); upperBoundIndex++; } if (findTypeParameterConstraint( altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex) != null) { throw new AlternativeSignatureMismatchException( "Extra upper bound #%d for type parameter %s", upperBoundIndex, originalTypeParamDescriptor.getName()); } altParamDescriptor.setInitialized(); altTypeParameters.add(altParamDescriptor); } }
private void computeValueParameters( @NotNull List<ValueParameterDescriptor> parameterDescriptors) { if (parameterDescriptors.size() != altFunDeclaration.getValueParameters().size()) { throw new AlternativeSignatureMismatchException( "Method signature has %d value parameters, but alternative signature has %d", parameterDescriptors.size(), altFunDeclaration.getValueParameters().size()); } List<ValueParameterDescriptor> altParamDescriptors = new ArrayList<ValueParameterDescriptor>(); for (int i = 0, size = parameterDescriptors.size(); i < size; i++) { ValueParameterDescriptor originalParameterDescriptor = parameterDescriptors.get(i); JetParameter annotationValueParameter = altFunDeclaration.getValueParameters().get(i); //noinspection ConstantConditions JetTypeElement alternativeTypeElement = annotationValueParameter.getTypeReference().getTypeElement(); assert alternativeTypeElement != null; JetType alternativeType; JetType alternativeVarargElementType; JetType originalParamVarargElementType = originalParameterDescriptor.getVarargElementType(); if (originalParamVarargElementType == null) { if (annotationValueParameter.isVarArg()) { throw new AlternativeSignatureMismatchException( "Parameter in method signature is not vararg, but in alternative signature it is vararg"); } alternativeType = TypeTransformingVisitor.computeType( alternativeTypeElement, originalParameterDescriptor.getType(), originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT); alternativeVarargElementType = null; } else { if (!annotationValueParameter.isVarArg()) { throw new AlternativeSignatureMismatchException( "Parameter in method signature is vararg, but in alternative signature it is not"); } alternativeVarargElementType = TypeTransformingVisitor.computeType( alternativeTypeElement, originalParamVarargElementType, originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT); alternativeType = KotlinBuiltIns.getInstance().getArrayType(alternativeVarargElementType); } Name altName = annotationValueParameter.getNameAsName(); altParamDescriptors.add( new ValueParameterDescriptorImpl( originalParameterDescriptor.getContainingDeclaration(), null, originalParameterDescriptor.getIndex(), originalParameterDescriptor.getAnnotations(), altName != null ? altName : originalParameterDescriptor.getName(), alternativeType, originalParameterDescriptor.declaresDefaultValue(), alternativeVarargElementType)); } altValueParameters = altParamDescriptors; }
@NotNull public Collection<FunctionDescriptor> getTopLevelFunctionDescriptorsByName( @NotNull String name, @NotNull JetSimpleNameExpression expression, @NotNull ResolveSession resolveSession, @NotNull GlobalSearchScope scope) { // name parameter can differ from expression.getReferenceName() when expression contains // completion suffix Name referenceName = expression.getIdentifier() == null ? JetPsiUtil.getConventionName(expression) : Name.identifier(name); if (referenceName == null || referenceName.toString().isEmpty()) { return Collections.emptyList(); } BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression); JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); if (jetScope == null) { return Collections.emptyList(); } Set<FunctionDescriptor> result = Sets.newHashSet(); Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName( referenceName.getName(), project, scope); for (PsiMethod method : topLevelFunctionPrototypes) { FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method); if (functionFQN != null) { JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false)); Collection<? extends DeclarationDescriptor> declarationDescriptors = new QualifiedExpressionResolver() .analyseImportReference( importDirective, jetScope, new BindingTraceContext(), resolveSession.getModuleConfiguration()); for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { if (declarationDescriptor instanceof FunctionDescriptor) { result.add((FunctionDescriptor) declarationDescriptor); } } } } Set<FqName> affectedPackages = Sets.newHashSet(); Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(referenceName.getName(), project, scope); for (JetNamedFunction jetNamedFunction : jetNamedFunctions) { PsiFile containingFile = jetNamedFunction.getContainingFile(); if (containingFile instanceof JetFile) { JetFile jetFile = (JetFile) containingFile; String packageName = jetFile.getPackageName(); if (packageName != null) { affectedPackages.add(new FqName(packageName)); } } } for (FqName affectedPackage : affectedPackages) { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(affectedPackage); assert packageDescriptor != null : "There's a function in stub index with invalid package: " + affectedPackage; JetScope memberScope = packageDescriptor.getMemberScope(); result.addAll(memberScope.getFunctions(referenceName)); } return result; }