Ejemplo n.º 1
0
 public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
   for (JetFile file : bodiesResolveContext.getFiles()) {
     checkDeclarationContainer(file);
   }
   for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) {
     if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue;
     checkDeclarationContainer(aClass);
   }
   for (JetObjectDeclaration objectDeclaration : bodiesResolveContext.getObjects().keySet()) {
     if (!bodiesResolveContext.completeAnalysisNeeded(objectDeclaration)) continue;
     checkDeclarationContainer(objectDeclaration);
   }
   for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry :
       bodiesResolveContext.getFunctions().entrySet()) {
     JetNamedFunction function = entry.getKey();
     SimpleFunctionDescriptor functionDescriptor = entry.getValue();
     if (!bodiesResolveContext.completeAnalysisNeeded(function)) continue;
     final JetType expectedReturnType =
         !function.hasBlockBody() && !function.hasDeclaredReturnType()
             ? NO_EXPECTED_TYPE
             : functionDescriptor.getReturnType();
     checkFunction(function, expectedReturnType);
   }
   for (Map.Entry<JetProperty, PropertyDescriptor> entry :
       bodiesResolveContext.getProperties().entrySet()) {
     JetProperty property = entry.getKey();
     if (!bodiesResolveContext.completeAnalysisNeeded(property)) continue;
     PropertyDescriptor propertyDescriptor = entry.getValue();
     checkProperty(property, propertyDescriptor);
   }
 }
  @Override
  public void processQuery(
      @NotNull ReferencesSearch.SearchParameters queryParameters,
      @NotNull Processor<PsiReference> consumer) {
    PsiElement element = queryParameters.getElementToSearch();
    if (element instanceof JetClass) {
      processJetClassOrObject((JetClass) element, queryParameters);
    } else if (element instanceof JetNamedFunction) {
      final JetNamedFunction function = (JetNamedFunction) element;
      String name = function.getName();
      if (name != null) {
        PsiMethod method =
            ApplicationManager.getApplication()
                .runReadAction(
                    new Computable<PsiMethod>() {
                      @Override
                      public PsiMethod compute() {
                        return LightClassUtil.getLightClassMethod(function);
                      }
                    });
        searchMethod(queryParameters, method);
      }
    } else if (element instanceof JetProperty) {
      final JetProperty property = (JetProperty) element;
      LightClassUtil.PropertyAccessorsPsiMethods propertyMethods =
          ApplicationManager.getApplication()
              .runReadAction(
                  new Computable<LightClassUtil.PropertyAccessorsPsiMethods>() {
                    @Override
                    public LightClassUtil.PropertyAccessorsPsiMethods compute() {
                      return LightClassUtil.getLightClassPropertyMethods(property);
                    }
                  });

      searchMethod(queryParameters, propertyMethods.getGetter());
      searchMethod(queryParameters, propertyMethods.getSetter());
    } else if (element instanceof JetObjectDeclarationName) {
      PsiElement parent = element.getParent();
      if (parent instanceof JetObjectDeclaration) {
        processJetClassOrObject((JetObjectDeclaration) parent, queryParameters);
      }
    }
  }
Ejemplo n.º 3
0
  @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();
    }
  }
  public AlternativeMethodSignatureData(
      @NotNull ExternalAnnotationResolver externalAnnotationResolver,
      @NotNull JavaMethod method,
      @Nullable JetType receiverType,
      @NotNull Project project,
      @NotNull List<ValueParameterDescriptor> valueParameters,
      @Nullable JetType originalReturnType,
      @NotNull List<TypeParameterDescriptor> methodTypeParameters,
      boolean hasSuperMethods) {
    String signature = SignaturesUtil.getKotlinSignature(externalAnnotationResolver, method);

    if (signature == null) {
      setAnnotated(false);
      altFunDeclaration = null;
      return;
    }

    if (receiverType != null) {
      throw new UnsupportedOperationException(
          "Alternative annotations for extension functions are not supported yet");
    }

    setAnnotated(true);
    altFunDeclaration = JetPsiFactory.createFunction(project, signature);

    originalToAltTypeParameters =
        DescriptorResolverUtils.recreateTypeParametersAndReturnMapping(methodTypeParameters, null);

    try {
      checkForSyntaxErrors(altFunDeclaration);
      checkEqualFunctionNames(altFunDeclaration, method);

      computeTypeParameters(methodTypeParameters);
      computeValueParameters(valueParameters);

      if (originalReturnType != null) {
        altReturnType =
            computeReturnType(
                originalReturnType,
                altFunDeclaration.getReturnTypeRef(),
                originalToAltTypeParameters);
      }

      if (hasSuperMethods) {
        checkParameterAndReturnTypesForOverridingMethods(
            valueParameters, methodTypeParameters, originalReturnType);
      }
    } catch (AlternativeSignatureMismatchException e) {
      setError(e.getMessage());
    }
  }
  private void computeTypeParameters(List<TypeParameterDescriptor> typeParameters) {
    if (typeParameters.size() != altFunDeclaration.getTypeParameters().size()) {
      throw new AlternativeSignatureMismatchException(
          "Method signature has %d type parameters, but alternative signature has %d",
          typeParameters.size(), altFunDeclaration.getTypeParameters().size());
    }

    altTypeParameters = new ArrayList<TypeParameterDescriptor>();

    for (int i = 0, size = typeParameters.size(); i < size; i++) {
      TypeParameterDescriptor originalTypeParamDescriptor = typeParameters.get(i);

      TypeParameterDescriptorImpl altParamDescriptor =
          originalToAltTypeParameters.get(originalTypeParamDescriptor);
      JetTypeParameter altTypeParameter = altFunDeclaration.getTypeParameters().get(i);

      int upperBoundIndex = 0;
      for (JetType upperBound : originalTypeParamDescriptor.getUpperBounds()) {
        JetTypeElement altTypeElement;

        if (upperBoundIndex == 0) {
          JetTypeReference extendsBound = altTypeParameter.getExtendsBound();
          if (extendsBound == null) { // default upper bound
            assert originalTypeParamDescriptor.getUpperBounds().size() == 1;
            altParamDescriptor.addDefaultUpperBound();
            break;
          } else {
            altTypeElement = extendsBound.getTypeElement();
          }
        } else {
          JetTypeConstraint constraint =
              findTypeParameterConstraint(
                  altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex);
          if (constraint == null) {
            throw new AlternativeSignatureMismatchException(
                "Upper bound #%d for type parameter %s is missing",
                upperBoundIndex, originalTypeParamDescriptor.getName());
          }
          //noinspection ConstantConditions
          altTypeElement = constraint.getBoundTypeReference().getTypeElement();
        }

        assert (altTypeElement != null);

        altParamDescriptor.addUpperBound(
            TypeTransformingVisitor.computeType(
                altTypeElement, upperBound,
                originalToAltTypeParameters, UPPER_BOUND));
        upperBoundIndex++;
      }

      if (findTypeParameterConstraint(
              altFunDeclaration, originalTypeParamDescriptor.getName(), upperBoundIndex)
          != null) {
        throw new AlternativeSignatureMismatchException(
            "Extra upper bound #%d for type parameter %s",
            upperBoundIndex, originalTypeParamDescriptor.getName());
      }

      altParamDescriptor.setInitialized();
      altTypeParameters.add(altParamDescriptor);
    }
  }
  private void computeValueParameters(
      @NotNull List<ValueParameterDescriptor> parameterDescriptors) {
    if (parameterDescriptors.size() != altFunDeclaration.getValueParameters().size()) {
      throw new AlternativeSignatureMismatchException(
          "Method signature has %d value parameters, but alternative signature has %d",
          parameterDescriptors.size(), altFunDeclaration.getValueParameters().size());
    }

    List<ValueParameterDescriptor> altParamDescriptors = new ArrayList<ValueParameterDescriptor>();
    for (int i = 0, size = parameterDescriptors.size(); i < size; i++) {
      ValueParameterDescriptor originalParameterDescriptor = parameterDescriptors.get(i);
      JetParameter annotationValueParameter = altFunDeclaration.getValueParameters().get(i);

      //noinspection ConstantConditions
      JetTypeElement alternativeTypeElement =
          annotationValueParameter.getTypeReference().getTypeElement();
      assert alternativeTypeElement != null;

      JetType alternativeType;
      JetType alternativeVarargElementType;

      JetType originalParamVarargElementType = originalParameterDescriptor.getVarargElementType();
      if (originalParamVarargElementType == null) {
        if (annotationValueParameter.isVarArg()) {
          throw new AlternativeSignatureMismatchException(
              "Parameter in method signature is not vararg, but in alternative signature it is vararg");
        }

        alternativeType =
            TypeTransformingVisitor.computeType(
                alternativeTypeElement,
                originalParameterDescriptor.getType(),
                originalToAltTypeParameters,
                MEMBER_SIGNATURE_CONTRAVARIANT);
        alternativeVarargElementType = null;
      } else {
        if (!annotationValueParameter.isVarArg()) {
          throw new AlternativeSignatureMismatchException(
              "Parameter in method signature is vararg, but in alternative signature it is not");
        }

        alternativeVarargElementType =
            TypeTransformingVisitor.computeType(
                alternativeTypeElement, originalParamVarargElementType,
                originalToAltTypeParameters, MEMBER_SIGNATURE_CONTRAVARIANT);
        alternativeType = KotlinBuiltIns.getInstance().getArrayType(alternativeVarargElementType);
      }

      Name altName = annotationValueParameter.getNameAsName();

      altParamDescriptors.add(
          new ValueParameterDescriptorImpl(
              originalParameterDescriptor.getContainingDeclaration(),
              null,
              originalParameterDescriptor.getIndex(),
              originalParameterDescriptor.getAnnotations(),
              altName != null ? altName : originalParameterDescriptor.getName(),
              alternativeType,
              originalParameterDescriptor.declaresDefaultValue(),
              alternativeVarargElementType));
    }

    altValueParameters = altParamDescriptors;
  }
Ejemplo n.º 7
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;
  }