@Override public StackValue innerValue( DeclarationDescriptor d, LocalLookup localLookup, GenerationState state, MutableClosure closure, Type classType) { FunctionDescriptor vd = (FunctionDescriptor) d; boolean idx = localLookup != null && localLookup.lookupLocal(vd); if (!idx) return null; BindingContext bindingContext = state.getBindingContext(); Type localType = asmTypeForAnonymousClass(bindingContext, vd); MutableClosure localFunClosure = bindingContext.get(CLOSURE, bindingContext.get(CLASS_FOR_FUNCTION, vd)); if (localFunClosure != null && JvmCodegenUtil.isConst(localFunClosure)) { // This is an optimization: we can obtain an instance of a const closure simply by // GETSTATIC ...$instance // (instead of passing this instance to the constructor and storing as a field) return StackValue.field(localType, localType, JvmAbi.INSTANCE_FIELD, true); } String fieldName = "$" + vd.getName(); StackValue innerValue = StackValue.field(localType, classType, fieldName, false); closure.recordField(fieldName, localType); closure.captureVariable(new EnclosedValueDescriptor(fieldName, d, innerValue, localType)); return innerValue; }
@Override public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { ClassDescriptor classDescriptor = bindingContext.get(CLASS, expression.getObjectDeclaration()); if (classDescriptor == null) { // working around a problem with shallow analysis super.visitObjectLiteralExpression(expression); return; } final String name = inventAnonymousClassName(expression.getObjectDeclaration()); recordClosure( bindingTrace, expression.getObjectDeclaration(), classDescriptor, peekFromStack(classStack), JvmClassName.byInternalName(name), false); classStack.push(classDescriptor); //noinspection ConstantConditions nameStack.push(bindingContext.get(FQN, classDescriptor).getInternalName()); super.visitObjectLiteralExpression(expression); nameStack.pop(); classStack.pop(); }
// TODO: Make it work for properties public Collection<DeclarationDescriptor> getJetCallableExtensions( @NotNull Condition<String> acceptedNameCondition, @NotNull JetSimpleNameExpression expression, @NotNull ResolveSession resolveSession, @NotNull GlobalSearchScope searchScope) { Collection<DeclarationDescriptor> resultDescriptors = new ArrayList<DeclarationDescriptor>(); BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression); JetExpression receiverExpression = expression.getReceiverExpression(); if (receiverExpression != null) { JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression); JetScope scope = context.get(BindingContext.RESOLUTION_SCOPE, receiverExpression); if (expressionType != null && scope != null) { Collection<String> extensionFunctionsNames = getAllJetExtensionFunctionsNames(searchScope); Set<FqName> functionFQNs = new java.util.HashSet<FqName>(); // Collect all possible extension function qualified names for (String name : extensionFunctionsNames) { if (acceptedNameCondition.value(name)) { Collection<PsiElement> extensionFunctions = getJetExtensionFunctionsByName(name, searchScope); for (PsiElement extensionFunction : extensionFunctions) { if (extensionFunction instanceof JetNamedFunction) { functionFQNs.add(JetPsiUtil.getFQName((JetNamedFunction) extensionFunction)); } else if (extensionFunction instanceof PsiMethod) { FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN( (PsiMethod) extensionFunction); if (functionFQN != null) { functionFQNs.add(functionFQN); } } } } } // Iterate through the function with attempt to resolve found functions for (FqName functionFQN : functionFQNs) { for (CallableDescriptor functionDescriptor : ExpressionTypingUtils.canFindSuitableCall( functionFQN, project, receiverExpression, expressionType, scope, resolveSession.getModuleConfiguration())) { resultDescriptors.add(functionDescriptor); } } } } return resultDescriptors; }
private static JetDelegatorToSuperCall findSuperCall( BindingContext bindingContext, JetElement classOrObject) { if (!(classOrObject instanceof JetClassOrObject)) { return null; } if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) { return null; } for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) { if (specifier instanceof JetDelegatorToSuperCall) { JetType superType = bindingContext.get(TYPE, specifier.getTypeReference()); assert superType != null; ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); assert superClassDescriptor != null; if (!isInterface(superClassDescriptor)) { return (JetDelegatorToSuperCall) specifier; } } } return null; }
@NotNull public static JvmClassName classNameForScriptDescriptor( BindingContext bindingContext, @NotNull ScriptDescriptor scriptDescriptor) { ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); //noinspection ConstantConditions return fqn(bindingContext, classDescriptor); }
@Override public void visitObjectDeclaration(JetObjectDeclaration declaration) { if (declaration.getParent() instanceof JetObjectLiteralExpression || declaration.getParent() instanceof JetClassObject) { super.visitObjectDeclaration(declaration); } else { ClassDescriptor classDescriptor = bindingContext.get(CLASS, declaration); // working around a problem with shallow analysis if (classDescriptor == null) return; String name = getName(classDescriptor); recordClosure( bindingTrace, declaration, classDescriptor, peekFromStack(classStack), JvmClassName.byInternalName(name), false); classStack.push(classDescriptor); nameStack.push(name); super.visitObjectDeclaration(declaration); nameStack.pop(); classStack.pop(); } }
@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; }
public static boolean isVarCapturedInClosure( BindingContext bindingContext, DeclarationDescriptor descriptor) { if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false; VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar(); }
@Override public void visitJetFile(JetFile file) { if (file.isScript()) { //noinspection ConstantConditions final ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_FUNCTION, bindingContext.get(SCRIPT, file.getScript())); classStack.push(classDescriptor); //noinspection ConstantConditions nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName()); } else { nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/')); } file.acceptChildren(this); nameStack.pop(); if (file.isScript()) { classStack.pop(); } }
@NotNull public static JvmClassName classNameForAnonymousClass( @NotNull BindingContext bindingContext, @NotNull JetElement expression) { if (expression instanceof JetObjectLiteralExpression) { JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression; expression = jetObjectLiteralExpression.getObjectDeclaration(); } ClassDescriptor descriptor = bindingContext.get(CLASS, expression); if (descriptor == null) { SimpleFunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); assert functionDescriptor != null; return classNameForAnonymousClass(bindingContext, functionDescriptor); } return fqn(bindingContext, descriptor); }
@NotNull public static JvmClassName classNameForScriptPsi( BindingContext bindingContext, @NotNull JetScript script) { ScriptDescriptor scriptDescriptor = bindingContext.get(SCRIPT, script); if (scriptDescriptor == null) { throw new IllegalStateException("Script descriptor not found by PSI " + script); } return classNameForScriptDescriptor(bindingContext, scriptDescriptor); }
@NotNull public static Collection<JetFile> allFilesInNamespaces( BindingContext bindingContext, Collection<JetFile> files) { // todo: we use Set and add given files but ignoring other scripts because something non-clear // kept in binding // for scripts especially in case of REPL HashSet<FqName> names = new HashSet<FqName>(); for (JetFile file : files) { if (!file.isScript()) { names.add(JetPsiUtil.getFQName(file)); } } HashSet<JetFile> answer = new HashSet<JetFile>(); answer.addAll(files); for (FqName name : names) { NamespaceDescriptor namespaceDescriptor = bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, name); Collection<JetFile> jetFiles = bindingContext.get(NAMESPACE_TO_FILES, namespaceDescriptor); if (jetFiles != null) answer.addAll(jetFiles); } List<JetFile> sortedAnswer = new ArrayList<JetFile>(answer); Collections.sort( sortedAnswer, new Comparator<JetFile>() { @NotNull private String path(JetFile file) { VirtualFile virtualFile = file.getVirtualFile(); assert virtualFile != null : "VirtualFile is null for JetFile: " + file.getName(); return virtualFile.getPath(); } @Override public int compare(JetFile first, JetFile second) { return path(first).compareTo(path(second)); } }); return sortedAnswer; }
@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; }
private static boolean isArgumentTypeValid( BindingContext bindingContext, JetValueArgument argument, ValueParameterDescriptor param) { if (argument.getArgumentExpression() != null) { JetType paramType = getActualParameterType(param); JetType exprType = bindingContext.get(BindingContext.EXPRESSION_TYPE, argument.getArgumentExpression()); return exprType == null || JetTypeChecker.INSTANCE.isSubtypeOf(exprType, paramType); } return false; }
@Override @NotNull protected Collection<DeclarationDescriptor> getTargetDescriptors( @NotNull BindingContext context) { ResolvedCall<?> resolvedCall = context.get(RESOLVED_CALL, getExpression().getCalleeExpression()); if (resolvedCall instanceof VariableAsFunctionResolvedCall) { return Collections.<DeclarationDescriptor>singleton( ((VariableAsFunctionResolvedCall) resolvedCall).getCandidateDescriptor()); } return Collections.emptyList(); }
private JetKeywordToken findVisibilityChangeTo(JetFile file) { BindingContext bindingContext = AnalyzeSingleFileUtil.getContextForSingleFile(file); DeclarationDescriptor descriptor; if (element instanceof JetParameter) { descriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, element); } else { descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); } if (!(descriptor instanceof CallableMemberDescriptor)) return null; CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor; Visibility maxVisibility = null; for (CallableMemberDescriptor overriddenDescriptor : memberDescriptor.getOverriddenDescriptors()) { Visibility overriddenDescriptorVisibility = overriddenDescriptor.getVisibility(); if (maxVisibility == null) { maxVisibility = overriddenDescriptorVisibility; continue; } Integer compare = Visibilities.compare(maxVisibility, overriddenDescriptorVisibility); if (compare == null) { maxVisibility = Visibilities.PUBLIC; } else if (compare < 0) { maxVisibility = overriddenDescriptorVisibility; } } if (maxVisibility == memberDescriptor.getVisibility()) { return null; } JetKeywordToken modifier = null; if (maxVisibility == Visibilities.PUBLIC) { modifier = JetTokens.PUBLIC_KEYWORD; } else if (maxVisibility == Visibilities.PROTECTED) { modifier = JetTokens.PROTECTED_KEYWORD; } else if (maxVisibility == Visibilities.INTERNAL) { modifier = JetTokens.INTERNAL_KEYWORD; } return modifier; }
private static boolean isDeclaredInJava( @NotNull CallableDescriptor callableDescriptor, @NotNull BindingContext context) { CallableDescriptor descriptor = callableDescriptor; while (true) { if (Boolean.TRUE.equals(context.get(BindingContext.IS_DECLARED_IN_JAVA, descriptor))) { return true; } CallableDescriptor original = descriptor.getOriginal(); if (descriptor == original) break; descriptor = original; } return false; }
@Nullable private static String renderElement(@Nullable PsiElement element) { String elementText; String containerText = null; if (element instanceof JetFile) { elementText = ((JetFile) element).getName(); } else if (element instanceof JetNamedDeclaration) { BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement((JetElement) element); DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); if (descriptor == null) return null; if (element instanceof JetClassOrObject) { if (element instanceof JetObjectDeclaration && ((JetObjectDeclaration) element).isClassObject()) { descriptor = descriptor.getContainingDeclaration(); if (!(descriptor instanceof ClassDescriptor)) return null; elementText = renderClassOrObject((ClassDescriptor) descriptor); } else if (element instanceof JetEnumEntry) { elementText = ((JetEnumEntry) element).getName(); } else { if (((JetClassOrObject) element).getName() != null) { elementText = renderClassOrObject((ClassDescriptor) descriptor); } else { elementText = "[anonymous]"; } } } else if (element instanceof JetNamedFunction) { elementText = renderNamedFunction((FunctionDescriptor) descriptor); } else if (element instanceof JetProperty) { elementText = ((JetProperty) element).getName(); } else return null; DeclarationDescriptor containerDescriptor = descriptor.getContainingDeclaration(); while (containerDescriptor != null) { String name = containerDescriptor.getName().asString(); if (!name.startsWith("<")) { containerText = name; break; } containerDescriptor = containerDescriptor.getContainingDeclaration(); } } else return null; if (elementText == null) return null; return containerText != null ? containerText + "." + elementText : elementText; }
/** * Name suggestion types: 1. According to type: 1a. Primitive types to some short name 1b. Class * types according to class name camel humps: (AbCd => {abCd, cd}) 1c. Arrays => arrayOfInnerType * 2. Reference expressions according to reference name camel humps 3. Method call expression * according to method callee expression * * @param expression to suggest name for variable * @param validator to check scope for such names * @return possible names */ public static String[] suggestNames(JetExpression expression, JetNameValidator validator) { ArrayList<String> result = new ArrayList<String>(); BindingContext bindingContext = AnalyzeSingleFileUtil.getContextForSingleFile((JetFile) expression.getContainingFile()); JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); if (jetType != null) { addNamesForType(result, jetType, validator); } addNamesForExpression(result, expression, validator); if (result.isEmpty()) addName(result, "value", validator); return ArrayUtil.toStringArray(result); }
private void appendDescriptor(DeclarationDescriptor descriptor, String indent) { int startOffset = myBuilder.length(); myBuilder.append(DescriptorRenderer.COMPACT.render(descriptor)); int endOffset = myBuilder.length(); if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) { if (((CallableMemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { if (descriptor instanceof FunctionDescriptor) { myBuilder.append(" { ").append(DECOMPILED_COMMENT).append(" }"); endOffset = myBuilder.length(); } else { // descriptor instanceof PropertyDescriptor if (((PropertyDescriptor) descriptor).getModality() != Modality.ABSTRACT) { myBuilder.append(" ").append(DECOMPILED_COMMENT); } } } } else if (descriptor instanceof ClassDescriptor) { myBuilder.append(" {\n"); ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; boolean firstPassed = false; String subindent = indent + " "; if (classDescriptor.getClassObjectDescriptor() != null) { firstPassed = true; myBuilder.append(subindent).append("class "); appendDescriptor(classDescriptor.getClassObjectDescriptor(), subindent); } for (DeclarationDescriptor member : sortDeclarations(classDescriptor.getDefaultType().getMemberScope().getAllDescriptors())) { if (member.getContainingDeclaration() == descriptor) { if (firstPassed) { myBuilder.append("\n"); } else { firstPassed = true; } myBuilder.append(subindent); appendDescriptor(member, subindent); } } myBuilder.append(indent).append("}"); endOffset = myBuilder.length(); } myBuilder.append("\n"); PsiElement clsMember = myBindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); if (clsMember != null) { myClsMembersToRanges.put(clsMember, new TextRange(startOffset, endOffset)); } }
@Override public void visitEnumEntry(JetEnumEntry enumEntry) { ClassDescriptor descriptor = bindingContext.get(CLASS, enumEntry); assert descriptor != null; final boolean trivial = enumEntry.getDeclarations().isEmpty(); if (!trivial) { bindingTrace.record(ENUM_ENTRY_CLASS_NEED_SUBCLASS, descriptor); super.visitEnumEntry(enumEntry); } else { JvmClassName jvmClassName = bindingTrace.get(FQN, peekFromStack(classStack)); assert PsiCodegenPredictor.checkPredictedNameFromPsi(bindingTrace, descriptor, jvmClassName); bindingTrace.record(FQN, descriptor, jvmClassName); } }
@Override public void visitClassObject(JetClassObject classObject) { ClassDescriptor classDescriptor = bindingContext.get(CLASS, classObject.getObjectDeclaration()); assert classDescriptor != null; JvmClassName name = JvmClassName.byInternalName(peekFromStack(nameStack) + JvmAbi.CLASS_OBJECT_SUFFIX); recordClosure( bindingTrace, classObject, classDescriptor, peekFromStack(classStack), name, false); classStack.push(classDescriptor); nameStack.push(name.getInternalName()); super.visitClassObject(classObject); nameStack.pop(); classStack.pop(); }
private static Boolean isResolvedToDescriptor( JetValueArgumentList argumentList, FunctionDescriptor functionDescriptor, BindingContext bindingContext) { JetSimpleNameExpression callNameExpression = getCallSimpleNameExpression(argumentList); if (callNameExpression != null) { DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, callNameExpression); if (declarationDescriptor != null) { if (declarationDescriptor == functionDescriptor) { return true; } } } return false; }
@Override public void visitClass(JetClass klass) { ClassDescriptor classDescriptor = bindingContext.get(CLASS, klass); // working around a problem with shallow analysis if (classDescriptor == null) return; String name = getName(classDescriptor); recordClosure( bindingTrace, klass, classDescriptor, peekFromStack(classStack), JvmClassName.byInternalName(name), false); classStack.push(classDescriptor); nameStack.push(name); super.visitClass(klass); nameStack.pop(); classStack.pop(); }
@NotNull public Collection<ClassDescriptor> getTopLevelObjectsByName( @NotNull String name, @NotNull JetSimpleNameExpression expression, @NotNull ResolveSession resolveSession, @NotNull GlobalSearchScope scope) { BindingContext context = ResolveSessionUtils.resolveToExpression(resolveSession, expression); JetScope jetScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); if (jetScope == null) { return Collections.emptyList(); } Set<ClassDescriptor> result = Sets.newHashSet(); Collection<JetObjectDeclaration> topObjects = JetTopLevelShortObjectNameIndex.getInstance().get(name, project, scope); for (JetObjectDeclaration objectDeclaration : topObjects) { FqName fqName = JetPsiUtil.getFQName(objectDeclaration); assert fqName != null : "Local object declaration in JetTopLevelShortObjectNameIndex:" + objectDeclaration.getText(); result.addAll( ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession, fqName, true)); } for (PsiClass psiClass : JetFromJavaDescriptorHelper.getCompiledClassesForTopLevelObjects( project, GlobalSearchScope.allScope(project))) { String qualifiedName = psiClass.getQualifiedName(); if (qualifiedName != null) { FqName fqName = new FqName(qualifiedName); result.addAll( ResolveSessionUtils.getClassOrObjectDescriptorsByFqName(resolveSession, fqName, true)); } } return result; }
@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(); } }
private String inventAnonymousClassName(JetElement declaration) { String top = peekFromStack(nameStack); Integer cnt = anonymousSubclassesCount.get(top); if (cnt == null) { cnt = 0; } String name = top + "$" + (cnt + 1); ClassDescriptor descriptor = bindingContext.get(CLASS, declaration); if (descriptor == null) { if (declaration instanceof JetFunctionLiteralExpression || declaration instanceof JetNamedFunction || declaration instanceof JetObjectLiteralExpression) { } else { throw new IllegalStateException( "Class-less declaration which is not JetFunctionLiteralExpression|JetNamedFunction|JetObjectLiteralExpression : " + declaration.getClass().getName()); } } anonymousSubclassesCount.put(top, cnt + 1); return name; }
@Nullable public static JetChangeSignatureDialog createDialog( @NotNull PsiElement element, PsiElement context, Project project, Editor editor) { if (!CommonRefactoringUtil.checkReadOnlyStatus(project, element)) return null; BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()) .getBindingContext(); DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); if (descriptor instanceof ClassDescriptor) { descriptor = ((ClassDescriptor) descriptor).getUnsubstitutedPrimaryConstructor(); } if (descriptor instanceof FunctionDescriptorImpl) { for (ValueParameterDescriptor parameter : ((FunctionDescriptor) descriptor).getValueParameters()) { if (parameter.getVarargElementType() != null) { String message = JetRefactoringBundle.message("error.cant.refactor.vararg.functions"); CommonRefactoringUtil.showErrorHint( project, editor, message, REFACTORING_NAME, HelpID.CHANGE_SIGNATURE); return null; } } return new JetChangeSignatureDialog( project, new JetFunctionPlatformDescriptorImpl((FunctionDescriptor) descriptor, element), context); } else { String message = RefactoringBundle.getCannotRefactorMessage( JetRefactoringBundle.message( "error.wrong.caret.position.function.or.constructor.name")); CommonRefactoringUtil.showErrorHint( project, editor, message, REFACTORING_NAME, HelpID.CHANGE_SIGNATURE); return null; } }
@Override public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, expression); // working around a problem with shallow analysis if (functionDescriptor == null) return; String name = inventAnonymousClassName(expression); ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor); recordClosure( bindingTrace, expression, classDescriptor, peekFromStack(classStack), JvmClassName.byInternalName(name), true); classStack.push(classDescriptor); nameStack.push(name); super.visitFunctionLiteralExpression(expression); nameStack.pop(); classStack.pop(); }
private static JetValueArgumentList findCall(CreateParameterInfoContext context) { // todo: calls to this constructors, when we will have auxiliary constructors PsiFile file = context.getFile(); if (!(file instanceof JetFile)) return null; PsiElement element = file.findElementAt(context.getOffset()); while (element != null && !(element instanceof JetValueArgumentList)) { element = element.getParent(); } if (element == null) return null; JetValueArgumentList argumentList = (JetValueArgumentList) element; JetCallElement callExpression; if (element.getParent() instanceof JetCallElement) { callExpression = (JetCallElement) element.getParent(); } else { return null; } BindingContext bindingContext = AnalyzeSingleFileUtil.getContextForSingleFile((JetFile) file); JetExpression calleeExpression = callExpression.getCalleeExpression(); if (calleeExpression == null) return null; JetSimpleNameExpression refExpression = null; if (calleeExpression instanceof JetSimpleNameExpression) { refExpression = (JetSimpleNameExpression) calleeExpression; } else if (calleeExpression instanceof JetConstructorCalleeExpression) { JetConstructorCalleeExpression constructorCalleeExpression = (JetConstructorCalleeExpression) calleeExpression; if (constructorCalleeExpression.getConstructorReferenceExpression() instanceof JetSimpleNameExpression) { refExpression = (JetSimpleNameExpression) constructorCalleeExpression.getConstructorReferenceExpression(); } } if (refExpression != null) { JetScope scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, refExpression); DeclarationDescriptor placeDescriptor = null; if (scope != null) { placeDescriptor = scope.getContainingDeclaration(); } Collection<DeclarationDescriptor> variants = TipsManager.getReferenceVariants(refExpression, bindingContext); Name refName = refExpression.getReferencedNameAsName(); PsiReference[] references = refExpression.getReferences(); if (references.length == 0) return null; ArrayList<DeclarationDescriptor> itemsToShow = new ArrayList<DeclarationDescriptor>(); for (DeclarationDescriptor variant : variants) { if (variant instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) variant; if (functionDescriptor.getName().equals(refName)) { // todo: renamed functions? if (placeDescriptor != null && !JetVisibilityChecker.isVisible(placeDescriptor, functionDescriptor)) continue; itemsToShow.add(functionDescriptor); } } else if (variant instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) variant; if (classDescriptor.getName().equals(refName)) { // todo: renamed classes? for (ConstructorDescriptor constructorDescriptor : classDescriptor.getConstructors()) { if (placeDescriptor != null && !JetVisibilityChecker.isVisible(placeDescriptor, constructorDescriptor)) continue; itemsToShow.add(constructorDescriptor); } } } } context.setItemsToShow(ArrayUtil.toObjectArray(itemsToShow)); return argumentList; } return null; }