Example #1
0
  // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry
  private void checkSupertypeList(
      @NotNull MutableClassDescriptor supertypeOwner,
      @NotNull Map<JetTypeReference, JetType> supertypes,
      Set<TypeConstructor> allowedFinalSupertypes) {
    Set<TypeConstructor> typeConstructors = Sets.newHashSet();
    boolean classAppeared = false;
    for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
      JetTypeReference typeReference = entry.getKey();
      JetType supertype = entry.getValue();

      ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
      if (classDescriptor != null) {
        if (classDescriptor.getKind() != ClassKind.TRAIT) {
          if (classAppeared) {
            trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
          } else {
            classAppeared = true;
          }
        }
      } else {
        trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
      }

      TypeConstructor constructor = supertype.getConstructor();
      if (!typeConstructors.add(constructor)) {
        trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
      }

      if (constructor.isSealed() && !allowedFinalSupertypes.contains(constructor)) {
        trace.report(FINAL_SUPERTYPE.on(typeReference));
      }
    }
  }
Example #2
0
  @NotNull
  private static Set<DeclarationDescriptor> getTopLevelDescriptorsByFqName(
      @NotNull KotlinCodeAnalyzer resolveSession, @NotNull FqName fqName) {
    FqName parentFqName = fqName.parent();

    Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();

    LazyPackageDescriptor parentFragment = resolveSession.getPackageFragment(parentFqName);
    if (parentFragment != null) {
      // Filter out extension properties
      descriptors.addAll(
          KotlinPackage.filter(
              parentFragment.getMemberScope().getProperties(fqName.shortName()),
              new Function1<VariableDescriptor, Boolean>() {
                @Override
                public Boolean invoke(VariableDescriptor descriptor) {
                  return descriptor.getReceiverParameter() == null;
                }
              }));
    }

    ContainerUtil.addIfNotNull(descriptors, resolveSession.getPackageFragment(fqName));

    descriptors.addAll(resolveSession.getTopLevelClassDescriptors(fqName));
    return descriptors;
  }
Example #3
0
  // 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;
  }
Example #4
0
 /**
  * Get jet non-extension top-level function names. Method is allowed to give invalid names - all
  * result should be checked with getTopLevelFunctionDescriptorsByName().
  *
  * @return
  */
 @NotNull
 public Collection<String> getAllTopLevelFunctionNames() {
   Set<String> functionNames = new HashSet<String>();
   functionNames.addAll(JetShortFunctionNameIndex.getInstance().getAllKeys(project));
   functionNames.addAll(
       JetFromJavaDescriptorHelper.getPossiblePackageDeclarationsNames(
           project, GlobalSearchScope.allScope(project)));
   return functionNames;
 }
Example #5
0
  /**
   * Get jet extensions top-level function names. Method is allowed to give invalid names - all
   * result should be checked with getAllJetExtensionFunctionsByName().
   *
   * @return
   */
  @NotNull
  public Collection<String> getAllJetExtensionFunctionsNames(@NotNull GlobalSearchScope scope) {
    Set<String> extensionFunctionNames = new HashSet<String>();

    extensionFunctionNames.addAll(JetExtensionFunctionNameIndex.getInstance().getAllKeys(project));
    extensionFunctionNames.addAll(
        JetFromJavaDescriptorHelper.getTopExtensionFunctionNames(project, scope));

    return extensionFunctionNames;
  }
Example #6
0
  private void resolvePropertyDeclarationBodies() {

    // Member properties
    Set<JetProperty> processed = Sets.newHashSet();
    for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
      JetClass jetClass = entry.getKey();
      if (!context.completeAnalysisNeeded(jetClass)) continue;
      MutableClassDescriptor classDescriptor = entry.getValue();

      for (JetProperty property : jetClass.getProperties()) {
        final PropertyDescriptor propertyDescriptor = this.context.getProperties().get(property);
        assert propertyDescriptor != null;

        computeDeferredType(propertyDescriptor.getReturnType());

        JetExpression initializer = property.getInitializer();
        if (initializer != null) {
          ConstructorDescriptor primaryConstructor =
              classDescriptor.getUnsubstitutedPrimaryConstructor();
          if (primaryConstructor != null) {
            JetScope declaringScopeForPropertyInitializer =
                this.context.getDeclaringScopes().get(property);
            resolvePropertyInitializer(
                property, propertyDescriptor, initializer, declaringScopeForPropertyInitializer);
          }
        }

        resolvePropertyAccessors(property, propertyDescriptor);
        processed.add(property);
      }
    }

    // Top-level properties & properties of objects
    for (Map.Entry<JetProperty, PropertyDescriptor> entry :
        this.context.getProperties().entrySet()) {
      JetProperty property = entry.getKey();
      if (!context.completeAnalysisNeeded(property)) continue;
      if (processed.contains(property)) continue;

      final PropertyDescriptor propertyDescriptor = entry.getValue();

      computeDeferredType(propertyDescriptor.getReturnType());

      JetScope declaringScope = this.context.getDeclaringScopes().get(property);

      JetExpression initializer = property.getInitializer();
      if (initializer != null) {
        resolvePropertyInitializer(property, propertyDescriptor, initializer, declaringScope);
      }

      resolvePropertyAccessors(property, propertyDescriptor);
    }
  }
Example #7
0
  @NotNull
  public Collection<String> getAllTopLevelObjectNames() {
    Set<String> topObjectNames = new HashSet<String>();
    topObjectNames.addAll(JetTopLevelShortObjectNameIndex.getInstance().getAllKeys(project));

    Collection<PsiClass> classObjects =
        JetFromJavaDescriptorHelper.getCompiledClassesForTopLevelObjects(
            project, GlobalSearchScope.allScope(project));
    topObjectNames.addAll(
        Collections2.transform(
            classObjects,
            new Function<PsiClass, String>() {
              @Override
              public String apply(@Nullable PsiClass aClass) {
                assert aClass != null;
                return aClass.getName();
              }
            }));

    return topObjectNames;
  }
Example #8
0
  @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;
  }
Example #9
0
 private boolean isReachable(
     TypeConstructor from, TypeConstructor to, Set<TypeConstructor> visited) {
   if (!visited.add(from)) return false;
   for (JetType supertype : from.getSupertypes()) {
     TypeConstructor supertypeConstructor = supertype.getConstructor();
     if (supertypeConstructor == to) {
       return true;
     }
     if (isReachable(supertypeConstructor, to, visited)) {
       return true;
     }
   }
   return false;
 }
Example #10
0
  public void checkRedeclarationsInPackages(
      @NotNull KotlinCodeAnalyzer resolveSession,
      @NotNull Multimap<FqName, JetElement> topLevelFqNames) {
    for (Map.Entry<FqName, Collection<JetElement>> entry : topLevelFqNames.asMap().entrySet()) {
      FqName fqName = entry.getKey();
      Collection<JetElement> declarationsOrPackageDirectives = entry.getValue();

      if (fqName.isRoot()) continue;

      Set<DeclarationDescriptor> descriptors =
          getTopLevelDescriptorsByFqName(resolveSession, fqName);

      if (descriptors.size() > 1) {
        for (JetElement declarationOrPackageDirective : declarationsOrPackageDirectives) {
          PsiElement reportAt =
              declarationOrPackageDirective instanceof JetNamedDeclaration
                  ? declarationOrPackageDirective
                  : ((JetPackageDirective) declarationOrPackageDirective).getNameIdentifier();
          trace.report(Errors.REDECLARATION.on(reportAt, fqName.shortName().asString()));
        }
      }
    }
  }
 // Temporary. Duplicates logic from LazyClassTypeConstructor.isReachable
 private static boolean isReachable(
     MutableClassDescriptorLite from,
     MutableClassDescriptorLite to,
     Set<ClassDescriptor> visited) {
   if (!visited.add(from)) return false;
   for (JetType supertype : from.getSupertypes()) {
     TypeConstructor supertypeConstructor = supertype.getConstructor();
     if (supertypeConstructor.getDeclarationDescriptor() == to) {
       return true;
     }
     ClassifierDescriptor superclass = supertypeConstructor.getDeclarationDescriptor();
     if (superclass instanceof MutableClassDescriptorLite
         && isReachable((MutableClassDescriptorLite) superclass, to, visited)) {
       return true;
     }
   }
   return false;
 }
Example #12
0
  @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;
  }