public void checkRedeclarationsInInnerClassNames(@NotNull TopDownAnalysisContext c) { for (ClassDescriptorWithResolutionScopes classDescriptor : c.getDeclaredClasses().values()) { if (classDescriptor.getKind() == ClassKind.CLASS_OBJECT) { // Class objects should be considered during analysing redeclarations in classes continue; } Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors(); ClassDescriptorWithResolutionScopes classObj = classDescriptor.getClassObjectDescriptor(); if (classObj != null) { Collection<DeclarationDescriptor> classObjDescriptors = classObj.getScopeForMemberLookup().getOwnDeclaredDescriptors(); if (!classObjDescriptors.isEmpty()) { allDescriptors = Lists.newArrayList(allDescriptors); allDescriptors.addAll(classObjDescriptors); } } Multimap<Name, DeclarationDescriptor> descriptorMap = HashMultimap.create(); for (DeclarationDescriptor desc : allDescriptors) { if (desc instanceof ClassDescriptor || desc instanceof PropertyDescriptor) { descriptorMap.put(desc.getName(), desc); } } reportRedeclarations(descriptorMap); } }
@NotNull private MutablePackageFragmentDescriptor getOrCreatePackageFragmentForFile( @NotNull JetFile file) { JetPackageDirective packageDirective = file.getPackageDirective(); assert packageDirective != null : "scripts are not supported"; MutablePackageFragmentDescriptor fragment = packageFragmentProvider.getOrCreateFragment(packageDirective.getFqName()); ModuleDescriptor module = packageFragmentProvider.getModule(); DescriptorResolver.resolvePackageHeader( packageDirective, module, TypeHierarchyResolver.this.trace); trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, file, fragment); // Register files corresponding to this package // The trace currently does not support bi-di multimaps that would handle this task nicer FqName fqName = fragment.getFqName(); Collection<JetFile> files = trace.get(PACKAGE_TO_FILES, fqName); if (files == null) { files = Sets.newIdentityHashSet(); } files.add(file); trace.record(BindingContext.PACKAGE_TO_FILES, fqName, files); return fragment; }
@NotNull public static Collection<ClassDescriptor> getClassOrObjectDescriptorsByFqName( @NotNull ResolveSession resolveSession, @NotNull FqName fqName, boolean includeObjectDeclarations) { if (fqName.isRoot()) { return Collections.emptyList(); } Collection<ClassDescriptor> classDescriptors = Lists.newArrayList(); FqName packageFqName = fqName.parent(); while (true) { NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(packageFqName); if (packageDescriptor != null) { FqName classInPackagePath = new FqName(QualifiedNamesUtil.tail(packageFqName, fqName)); Collection<ClassDescriptor> descriptors = getClassOrObjectDescriptorsByFqName( packageDescriptor, classInPackagePath, includeObjectDeclarations); classDescriptors.addAll(descriptors); } if (packageFqName.isRoot()) { break; } else { packageFqName = packageFqName.parent(); } } return classDescriptors; }
// 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 void recordInnerClass( @NotNull BindingTrace bindingTrace, @NotNull ClassDescriptor outer, @NotNull ClassDescriptor inner) { Collection<ClassDescriptor> innerClasses = bindingTrace.get(INNER_CLASSES, outer); if (innerClasses == null) { innerClasses = new ArrayList<ClassDescriptor>(); bindingTrace.record(INNER_CLASSES, outer, innerClasses); } innerClasses.add(inner); }
/** Return class names form jet sources in given scope which should be visible as Java classes. */ @NotNull @Override public PsiClass[] getClassesByName( @NotNull @NonNls String name, @NotNull GlobalSearchScope scope) { List<PsiClass> result = new ArrayList<PsiClass>(); IDELightClassGenerationSupport lightClassGenerationSupport = IDELightClassGenerationSupport.getInstanceForIDE(project); MultiMap<String, FqName> packageClasses = lightClassGenerationSupport.getAllPackageClasses(scope); // .namespace classes can not be indexed, since they have no explicit declarations Collection<FqName> fqNames = packageClasses.get(name); if (!fqNames.isEmpty()) { for (FqName fqName : fqNames) { PsiClass psiClass = JavaElementFinder.getInstance(project).findClass(fqName.getFqName(), scope); if (psiClass != null) { result.add(psiClass); } } } // Quick check for classes from getAllClassNames() Collection<JetClassOrObject> classOrObjects = JetShortClassNameIndex.getInstance().get(name, project, scope); if (classOrObjects.isEmpty()) { return result.toArray(new PsiClass[result.size()]); } for (JetClassOrObject classOrObject : classOrObjects) { FqName fqName = JetPsiUtil.getFQName(classOrObject); if (fqName != null) { assert fqName.shortName().getName().equals(name) : "A declaration obtained from index has non-matching name:\n" + "in index: " + name + "\n" + "declared: " + fqName.shortName() + "(" + fqName + ")"; PsiClass psiClass = JavaElementFinder.getInstance(project).findClass(fqName.getFqName(), scope); if (psiClass != null) { result.add(psiClass); } } } return result.toArray(new PsiClass[result.size()]); }
public Collection<ClassDescriptor> getJetClassesDescriptors( @NotNull Condition<String> acceptedShortNameCondition, @NotNull KotlinCodeAnalyzer analyzer) { Collection<ClassDescriptor> classDescriptors = new ArrayList<ClassDescriptor>(); for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) { FqName classFQName = new FqName(fqName); if (acceptedShortNameCondition.value(classFQName.shortName().getName())) { classDescriptors.addAll( ResolveSessionUtils.getClassDescriptorsByFqName(analyzer, classFQName)); } } return classDescriptors; }
/** Return jet class names form jet project sources which should be visible from java. */ @NotNull @Override public String[] getAllClassNames() { Collection<String> classNames = JetShortClassNameIndex.getInstance().getAllKeys(project); // .namespace classes can not be indexed, since they have no explicit declarations IDELightClassGenerationSupport lightClassGenerationSupport = IDELightClassGenerationSupport.getInstanceForIDE(project); Set<String> packageClassShortNames = lightClassGenerationSupport .getAllPackageClasses(GlobalSearchScope.allScope(project)) .keySet(); classNames.addAll(packageClassShortNames); return ArrayUtil.toStringArray(classNames); }
private void prepareForDeferredCall( @NotNull JetScope outerScope, @NotNull DeclarationDescriptor descriptorForDeferredResolve, @NotNull JetDeclarationContainer container) { forDeferredResolve.add(container); c.normalScope.put(container, outerScope); c.forDeferredResolver.put(container, descriptorForDeferredResolve); }
private void findAndDisconnectLoopsInTypeHierarchy(Collection<JetType> supertypes) { for (Iterator<JetType> iterator = supertypes.iterator(); iterator.hasNext(); ) { JetType supertype = iterator.next(); if (isReachable(supertype.getConstructor(), this, new HashSet<TypeConstructor>())) { iterator.remove(); } } }
private void checkRedeclarationsInPackages(@NotNull TopDownAnalysisContext c) { for (MutablePackageFragmentDescriptor packageFragment : Sets.newHashSet(c.getPackageFragments().values())) { PackageViewDescriptor packageView = packageFragment.getContainingDeclaration().getPackage(packageFragment.getFqName()); JetScope packageViewScope = packageView.getMemberScope(); Multimap<Name, DeclarationDescriptor> simpleNameDescriptors = packageFragment.getMemberScope().getDeclaredDescriptorsAccessibleBySimpleName(); for (Name name : simpleNameDescriptors.keySet()) { // Keep only properties with no receiver Collection<DeclarationDescriptor> descriptors = Collections2.filter( simpleNameDescriptors.get(name), new Predicate<DeclarationDescriptor>() { @Override public boolean apply(@Nullable DeclarationDescriptor descriptor) { if (descriptor instanceof PropertyDescriptor) { PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; return propertyDescriptor.getReceiverParameter() == null; } return true; } }); ContainerUtil.addIfNotNull(descriptors, packageViewScope.getPackage(name)); if (descriptors.size() > 1) { for (DeclarationDescriptor declarationDescriptor : descriptors) { for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) { assert declaration != null : "Null declaration for descriptor: " + declarationDescriptor + " " + (declarationDescriptor != null ? DescriptorRenderer.FQ_NAMES_IN_TYPES.render(declarationDescriptor) : ""); trace.report( REDECLARATION.on(declaration, declarationDescriptor.getName().asString())); } } } } } }
private static Collection<ClassDescriptor> getClassOrObjectDescriptorsByFqName( NamespaceDescriptor packageDescriptor, FqName path, boolean includeObjectDeclarations) { if (path.isRoot()) { return Collections.emptyList(); } Collection<JetScope> scopes = Arrays.asList(packageDescriptor.getMemberScope()); List<Name> names = path.pathSegments(); if (names.size() > 1) { for (Name subName : path.pathSegments().subList(0, names.size() - 1)) { Collection<JetScope> tempScopes = Lists.newArrayList(); for (JetScope scope : scopes) { ClassifierDescriptor classifier = scope.getClassifier(subName); if (classifier instanceof ClassDescriptorBase) { ClassDescriptorBase classDescriptor = (ClassDescriptorBase) classifier; tempScopes.add(classDescriptor.getUnsubstitutedInnerClassesScope()); } } scopes = tempScopes; } } Name shortName = path.shortName(); Collection<ClassDescriptor> resultClassifierDescriptors = Lists.newArrayList(); for (JetScope scope : scopes) { ClassifierDescriptor classifier = scope.getClassifier(shortName); if (classifier instanceof ClassDescriptor) { resultClassifierDescriptors.add((ClassDescriptor) classifier); } if (includeObjectDeclarations) { ClassDescriptor objectDescriptor = scope.getObjectDescriptor(shortName); if (objectDescriptor != null) { resultClassifierDescriptors.add(objectDescriptor); } } } return resultClassifierDescriptors; }
private void reportRedeclarations(@NotNull Multimap<Name, DeclarationDescriptor> descriptorMap) { Set<Pair<PsiElement, Name>> redeclarations = Sets.newHashSet(); for (Name name : descriptorMap.keySet()) { Collection<DeclarationDescriptor> descriptors = descriptorMap.get(name); if (descriptors.size() > 1) { // We mustn't compare PropertyDescriptor with PropertyDescriptor because we do this at // OverloadResolver for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof ClassDescriptor) { for (DeclarationDescriptor descriptor2 : descriptors) { if (descriptor == descriptor2) { continue; } redeclarations.add( Pair.create( BindingContextUtils.classDescriptorToDeclaration( trace.getBindingContext(), (ClassDescriptor) descriptor), descriptor.getName())); if (descriptor2 instanceof PropertyDescriptor) { redeclarations.add( Pair.create( BindingContextUtils.descriptorToDeclaration( trace.getBindingContext(), descriptor2), descriptor2.getName())); } } } } } } for (Pair<PsiElement, Name> redeclaration : redeclarations) { trace.report( REDECLARATION.on(redeclaration.getFirst(), redeclaration.getSecond().asString())); } }