@Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (!super.isAvailable(project, editor, file)) { return false; } BindingContext context = KotlinCacheManager.getInstance(project).getDeclarationsFromProject().getBindingContext(); AnnotationDescriptor annotationDescriptor = context.get(BindingContext.ANNOTATION, annotationEntry); if (annotationDescriptor == null) { return false; } annotationType = annotationDescriptor.getType(); DeclarationDescriptor declarationDescriptor = annotationType.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor == null) { return false; } PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, declarationDescriptor); if (declaration instanceof JetClass) { annotationClass = (JetClass) declaration; return annotationClass.isWritable(); } return false; }
@NotNull private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> getSuperclassToFunctionsMultimap( @NotNull PsiMethodWrapper method, @NotNull BindingContext bindingContext, @NotNull ClassDescriptor containingClass) { Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create(); Name functionName = Name.identifier(method.getName()); int parameterCount = method.getParameters().size(); for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) { ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor(); assert klass != null; FqName fqName = DescriptorUtils.getFQName(klass).toSafe(); for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) { if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) { PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun); if (declaration instanceof PsiMethod) { result.put(fqName, Pair.create(fun, (PsiMethod) declaration)); } // else declaration is null or JetNamedFunction: both cases are processed later } } } return result; }
private static String renderParameter( ValueParameterDescriptor descriptor, boolean named, BindingContext bindingContext) { StringBuilder builder = new StringBuilder(); if (named) builder.append("["); if (descriptor.getVarargElementType() != null) { builder.append("vararg "); } builder .append(descriptor.getName()) .append(": ") .append(DescriptorRenderer.TEXT.renderType(getActualParameterType(descriptor))); if (descriptor.hasDefaultValue()) { PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); String defaultExpression = "?"; if (element instanceof JetParameter) { JetParameter parameter = (JetParameter) element; JetExpression defaultValue = parameter.getDefaultValue(); if (defaultValue != null) { if (defaultValue instanceof JetConstantExpression) { JetConstantExpression constantExpression = (JetConstantExpression) defaultValue; defaultExpression = constantExpression.getText(); if (defaultExpression.length() > 10) { if (defaultExpression.startsWith("\"")) defaultExpression = "\"...\""; else if (defaultExpression.startsWith("\'")) defaultExpression = "\'...\'"; else defaultExpression = defaultExpression.substring(0, 7) + "..."; } } } } builder.append(" = ").append(defaultExpression); } if (named) builder.append("]"); return builder.toString(); }
public static boolean isNamedFun(DeclarationDescriptor fd, BindingContext bindingContext) { PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, fd); if (psiElement instanceof JetNamedFunction) { return true; } return false; }
public static boolean isLocalFun(DeclarationDescriptor fd, BindingContext bindingContext) { PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, fd); if (psiElement instanceof JetNamedFunction && psiElement.getParent() instanceof JetBlockExpression) { return true; } return false; }
@Nullable @Override public PsiElement findTargetMember(PsiElement element) { if (PsiTreeUtil.getParentOfType(element, JetParameterList.class) != null) { return PsiTreeUtil.getParentOfType(element, JetFunction.class, JetClass.class); } JetTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, JetTypeParameterList.class); if (typeParameterList != null) { return PsiTreeUtil.getParentOfType(typeParameterList, JetFunction.class, JetClass.class); } PsiElement elementParent = element.getParent(); if (elementParent instanceof JetNamedFunction && ((JetNamedFunction) elementParent).getNameIdentifier() == element) { return elementParent; } if (elementParent instanceof JetClass && ((JetClass) elementParent).getNameIdentifier() == element) { return elementParent; } JetCallElement call = PsiTreeUtil.getParentOfType( element, JetCallExpression.class, JetDelegatorToSuperCall.class); if (call != null) { JetExpression receiverExpr = call instanceof JetCallExpression ? call.getCalleeExpression() : ((JetDelegatorToSuperCall) call) .getCalleeExpression() .getConstructorReferenceExpression(); if (receiverExpr instanceof JetSimpleNameExpression) { BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()) .getBindingContext(); DeclarationDescriptor descriptor = bindingContext.get( BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) receiverExpr); if (descriptor != null) { PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor); if (declaration instanceof JetNamedFunction || declaration instanceof JetClass) { return declaration; } } } } return null; }
/** * Add import directive corresponding to a type to file when it is needed. * * @param type type to import * @param file file where import directive should be added */ public static void addImportDirectivesIfNeeded(@NotNull JetType type, @NotNull JetFile file) { if (JetPluginUtil.checkTypeIsStandard(type, file.getProject()) || ErrorUtils.isErrorType(type)) { return; } BindingContext bindingContext = getContextForSingleFile(file); PsiElement element = BindingContextUtils.descriptorToDeclaration( bindingContext, type.getMemberScope().getContainingDeclaration()); if (element != null && element.getContainingFile() == file) { // declaration is in the same file, so no import is needed return; } for (ClassDescriptor clazz : TypeUtils.getAllClassDescriptors(type)) { addImportDirective(DescriptorUtils.getFQName(getTopLevelClass(clazz)).toSafe(), file); } }
@NotNull public static LookupElement createLookupElement( @NotNull KotlinCodeAnalyzer analyzer, @NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) { if (descriptor instanceof CallableMemberDescriptor) { CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) descriptor; while (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { // TODO: need to know all of them callableMemberDescriptor = callableMemberDescriptor.getOverriddenDescriptors().iterator().next(); } descriptor = callableMemberDescriptor; } return createLookupElement( analyzer, descriptor, BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)); }
private static String renderParameter( ValueParameterDescriptor parameter, boolean named, BindingContext bindingContext) { 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 (parameter.hasDefaultValue()) { PsiElement parameterDeclaration = BindingContextUtils.descriptorToDeclaration(bindingContext, parameter); builder.append(" = ").append(getDefaultExpressionString(parameterDeclaration)); } if (named) builder.append("]"); return builder.toString(); }