@NotNull private static LookupResult lookupSimpleNameReference( @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope, @NotNull LookupMode lookupMode, boolean packageLevel) { Name referencedName = referenceExpression.getReferencedNameAsName(); Collection<DeclarationDescriptor> descriptors = Sets.newLinkedHashSet(); PackageViewDescriptor packageDescriptor = outerScope.getPackage(referencedName); if (packageDescriptor != null) { descriptors.add(packageDescriptor); } ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName); if (classifierDescriptor != null) { descriptors.add(classifierDescriptor); } if (lookupMode == LookupMode.EVERYTHING) { descriptors.addAll(outerScope.getFunctions(referencedName)); descriptors.addAll(outerScope.getProperties(referencedName)); VariableDescriptor localVariable = outerScope.getLocalVariable(referencedName); if (localVariable != null) { descriptors.add(localVariable); } } return new LookupResult(descriptors, outerScope, packageLevel); }
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; } JetValueArgumentList argumentList = PsiTreeUtil.getParentOfType( file.findElementAt(context.getOffset()), JetValueArgumentList.class); if (argumentList == null) { return null; } final JetSimpleNameExpression callNameExpression = getCallSimpleNameExpression(argumentList); if (callNameExpression == null) { return null; } PsiReference[] references = callNameExpression.getReferences(); if (references.length == 0) { return null; } ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(callNameExpression.getContainingJetFile()); final BindingContext bindingContext = resolutionFacade.analyze(callNameExpression, BodyResolveMode.FULL); ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(callNameExpression); JetScope scope = bindingContext.get(BindingContext.RESOLUTION_SCOPE, callNameExpression); final DeclarationDescriptor placeDescriptor; if (scope != null) { placeDescriptor = scope.getContainingDeclaration(); } else { placeDescriptor = null; } Function1<DeclarationDescriptor, Boolean> visibilityFilter = new Function1<DeclarationDescriptor, Boolean>() { @Override public Boolean invoke(DeclarationDescriptor descriptor) { if (placeDescriptor == null) return true; if (!(descriptor instanceof DeclarationDescriptorWithVisibility)) return true; return CorePackage.isVisible( (DeclarationDescriptorWithVisibility) descriptor, placeDescriptor, bindingContext, callNameExpression); } }; final Name refName = callNameExpression.getReferencedNameAsName(); Function1<Name, Boolean> nameFilter = new Function1<Name, Boolean>() { @Override public Boolean invoke(Name name) { return name.equals(refName); } }; Collection<DeclarationDescriptor> variants = new ReferenceVariantsHelper( bindingContext, moduleDescriptor, file.getProject(), visibilityFilter) .getReferenceVariants( callNameExpression, new DescriptorKindFilter( DescriptorKindFilter.FUNCTIONS_MASK | DescriptorKindFilter.CLASSIFIERS_MASK, Collections.<DescriptorKindExclude>emptyList()), nameFilter, false, false); Collection<Pair<? extends DeclarationDescriptor, ResolutionFacade>> itemsToShow = new ArrayList<Pair<? extends DeclarationDescriptor, ResolutionFacade>>(); for (DeclarationDescriptor variant : variants) { if (variant instanceof FunctionDescriptor) { // todo: renamed functions? itemsToShow.add(Pair.create((FunctionDescriptor) variant, resolutionFacade)); } else if (variant instanceof ClassDescriptor) { // todo: renamed classes? for (ConstructorDescriptor constructorDescriptor : ((ClassDescriptor) variant).getConstructors()) { itemsToShow.add(Pair.create(constructorDescriptor, resolutionFacade)); } } } context.setItemsToShow(ArrayUtil.toObjectArray(itemsToShow)); return argumentList; }
@Override public void updateUI( Pair<? extends FunctionDescriptor, ResolutionFacade> itemToShow, @NotNull ParameterInfoUIContext context) { // todo: when we will have ability to pass Array as vararg, implement such feature here too? if (context == null || context.getParameterOwner() == null || !context.getParameterOwner().isValid()) { context.setUIComponentEnabled(false); return; } PsiElement parameterOwner = context.getParameterOwner(); if (!(parameterOwner instanceof JetValueArgumentList)) { context.setUIComponentEnabled(false); return; } JetValueArgumentList argumentList = (JetValueArgumentList) parameterOwner; FunctionDescriptor functionDescriptor = itemToShow.first; ResolutionFacade resolutionFacade = itemToShow.second; List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters(); List<JetValueArgument> valueArguments = argumentList.getArguments(); int currentParameterIndex = context.getCurrentParameterIndex(); int boldStartOffset = -1; int boldEndOffset = -1; boolean isGrey = false; boolean isDeprecated = KotlinBuiltIns.isDeprecated(functionDescriptor); boolean[] usedIndexes = new boolean[valueParameters.size()]; Arrays.fill(usedIndexes, false); boolean namedMode = false; if (!isIndexValid(valueParameters, currentParameterIndex)) { isGrey = true; } StringBuilder builder = new StringBuilder(); PsiElement owner = context.getParameterOwner(); BindingContext bindingContext = resolutionFacade.analyze((JetElement) owner, BodyResolveMode.FULL); for (int i = 0; i < valueParameters.size(); ++i) { if (i != 0) { builder.append(", "); } boolean highlightParameter = i == currentParameterIndex || (!namedMode && i < currentParameterIndex && Iterables.getLast(valueParameters).getVarargElementType() != null); if (highlightParameter) { boldStartOffset = builder.length(); } if (!namedMode) { if (valueArguments.size() > i) { JetValueArgument argument = valueArguments.get(i); if (argument.isNamed()) { namedMode = true; } else { ValueParameterDescriptor param = valueParameters.get(i); builder.append(renderParameter(param, false)); if (i <= currentParameterIndex && !isArgumentTypeValid(bindingContext, argument, param)) { isGrey = true; } usedIndexes[i] = true; } } else { ValueParameterDescriptor param = valueParameters.get(i); builder.append(renderParameter(param, false)); } } if (namedMode) { boolean takeAnyArgument = true; if (valueArguments.size() > i) { JetValueArgument argument = valueArguments.get(i); if (argument.isNamed()) { for (int j = 0; j < valueParameters.size(); ++j) { JetSimpleNameExpression referenceExpression = argument.getArgumentName().getReferenceExpression(); ValueParameterDescriptor param = valueParameters.get(j); if (referenceExpression != null && !usedIndexes[j] && param.getName().equals(referenceExpression.getReferencedNameAsName())) { takeAnyArgument = false; usedIndexes[j] = true; builder.append(renderParameter(param, true)); if (i < currentParameterIndex && !isArgumentTypeValid(bindingContext, argument, param)) { isGrey = true; } break; } } } } if (takeAnyArgument) { if (i < currentParameterIndex) { isGrey = true; } for (int j = 0; j < valueParameters.size(); ++j) { ValueParameterDescriptor param = valueParameters.get(j); if (!usedIndexes[j]) { usedIndexes[j] = true; builder.append(renderParameter(param, true)); break; } } } } if (highlightParameter) { boldEndOffset = builder.length(); } } if (valueParameters.size() == 0) { builder.append(CodeInsightBundle.message("parameter.info.no.parameters")); } assert !builder.toString().isEmpty() : "A message about 'no parameters' or some parameters should be present: " + functionDescriptor; Color color = isResolvedToDescriptor(argumentList, functionDescriptor, bindingContext) ? GREEN_BACKGROUND : context.getDefaultParameterColor(); context.setupUIComponentPresentation( builder.toString(), boldStartOffset, boldEndOffset, isGrey, isDeprecated, false, color); }