Esempio n. 1
0
  public static boolean doNeedImport(
      @NotNull ImportPath importPath, @Nullable String aliasName, @NotNull JetFile file) {
    if (QualifiedNamesUtil.getFirstSegment(importPath.fqnPart().getFqName())
        .equals(JavaDescriptorResolver.JAVA_ROOT.getName())) {
      FqName withoutJavaRoot = QualifiedNamesUtil.withoutFirstSegment(importPath.fqnPart());
      importPath = new ImportPath(withoutJavaRoot, importPath.isAllUnder());
    }

    if (isImportedByDefault(importPath, null, JetPsiUtil.getFQName(file))) {
      return false;
    }

    List<JetImportDirective> importDirectives = file.getImportDirectives();

    if (!importDirectives.isEmpty()) {
      // Check if import is already present
      for (JetImportDirective directive : importDirectives) {
        ImportPath existentImportPath = JetPsiUtil.getImportPath(directive);
        if (directive.getAliasName() == null && aliasName == null) {
          if (existentImportPath != null
              && QualifiedNamesUtil.isImported(existentImportPath, importPath)) {
            return false;
          }
        }
      }
    }

    return true;
  }
Esempio n. 2
0
  protected static PsiElement adjustSibling(
      @NotNull Editor editor,
      @NotNull LineRange sourceRange,
      @NotNull MoveInfo info,
      boolean down) {
    PsiElement element = down ? sourceRange.lastElement : sourceRange.firstElement;
    PsiElement sibling = down ? element.getNextSibling() : element.getPrevSibling();

    PsiElement whiteSpaceTestSubject = sibling;
    if (sibling == null) {
      PsiElement parent = element.getParent();
      if (parent != null && isBracelessBlock(parent)) {
        whiteSpaceTestSubject = down ? parent.getNextSibling() : parent.getPrevSibling();
      }
    }

    if (whiteSpaceTestSubject instanceof PsiWhiteSpace) {
      if (getElementLineCount(whiteSpaceTestSubject, editor) > 1) {
        int nearLine = down ? sourceRange.endLine : sourceRange.startLine - 1;

        info.toMove = sourceRange;
        info.toMove2 = new LineRange(nearLine, nearLine + 1);
        info.indentTarget = false;

        return null;
      }

      if (sibling != null) {
        sibling = firstNonWhiteElement(sibling, down);
      }
    }

    if (sibling == null) {
      JetCallExpression callExpression =
          PsiTreeUtil.getParentOfType(element, JetCallExpression.class);
      if (callExpression != null) {
        JetBlockExpression dslBlock = getDSLLambdaBlock(callExpression, down);
        if (PsiTreeUtil.isAncestor(dslBlock, element, false)) {
          //noinspection ConstantConditions
          PsiElement blockParent = dslBlock.getParent();
          return down
              ? JetPsiUtil.findChildByType(blockParent, JetTokens.RBRACE)
              : JetPsiUtil.findChildByType(blockParent, JetTokens.LBRACE);
        }
      }

      info.toMove2 = null;
      return null;
    }

    return sibling;
  }
Esempio n. 3
0
  @Nullable
  private static JetBlockExpression findClosestBlock(
      @NotNull PsiElement anchor, boolean down, boolean strict) {
    PsiElement current = PsiTreeUtil.getParentOfType(anchor, JetBlockExpression.class, strict);
    while (current != null) {
      PsiElement parent = current.getParent();
      if (parent instanceof JetClassBody
          || parent instanceof JetClassInitializer
          || parent instanceof JetNamedFunction
          || (parent instanceof JetProperty && !((JetProperty) parent).isLocal())) {
        return null;
      }

      if (parent instanceof JetBlockExpression) return (JetBlockExpression) parent;

      PsiElement sibling = down ? current.getNextSibling() : current.getPrevSibling();
      if (sibling != null) {
        //noinspection unchecked
        JetBlockExpression block =
            (JetBlockExpression)
                JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK);
        if (block != null) return block;

        current = sibling;
      } else {
        current = parent;
      }
    }

    return null;
  }
Esempio n. 4
0
  /** Check that import is useless. */
  private static boolean isImportedByDefault(
      @NotNull ImportPath importPath, @NotNull JetFile jetFile) {
    if (importPath.fqnPart().isRoot()) {
      return true;
    }

    if (!importPath.isAllUnder() && !importPath.hasAlias()) {
      // Single element import without .* and alias is useless
      if (QualifiedNamesUtil.isOneSegmentFQN(importPath.fqnPart())) {
        return true;
      }

      // There's no need to import a declaration from the package of current file
      if (JetPsiUtil.getFQName(jetFile).equals(importPath.fqnPart().parent())) {
        return true;
      }
    }

    if (isImportedWithKotlinDefault(importPath)) return true;

    if (KotlinFrameworkDetector.isJsKotlinModule(jetFile)) {
      return isImportedWithJsDefault(importPath);
    } else {
      return isImportedWithJavaDefault(importPath);
    }
  }
Esempio n. 5
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;
  }
Esempio n. 6
0
  @Nullable
  private static JetBlockExpression getDSLLambdaBlock(@NotNull PsiElement element, boolean down) {
    JetCallExpression callExpression =
        (JetCallExpression)
            JetPsiUtil.getOutermostDescendantElement(element, down, IS_CALL_EXPRESSION);
    if (callExpression == null) return null;

    List<JetExpression> functionLiterals = callExpression.getFunctionLiteralArguments();
    if (functionLiterals.isEmpty()) return null;

    return ((JetFunctionLiteralExpression) functionLiterals.get(0)).getBodyExpression();
  }
Esempio n. 7
0
  /** 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()]);
  }
Esempio n. 8
0
  private static BraceStatus checkForMovableUpClosingBrace(
      @NotNull PsiElement closingBrace,
      PsiElement block,
      @NotNull Editor editor,
      @NotNull MoveInfo info) {
    //noinspection unchecked
    PsiElement prev = JetPsiUtil.getLastChildByType(block, JetExpression.class);
    if (prev == null) return BraceStatus.NOT_MOVABLE;

    Document doc = editor.getDocument();

    info.toMove = new LineRange(closingBrace, closingBrace, doc);
    info.toMove2 = new LineRange(prev, prev, doc);
    info.indentSource = true;

    return BraceStatus.MOVABLE;
  }
Esempio n. 9
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;
  }
Esempio n. 10
0
  @Nullable
  private static LineRange getExpressionTargetRange(
      @NotNull Editor editor, @NotNull PsiElement sibling, boolean down) {
    if (sibling instanceof JetIfExpression && !down) {
      JetExpression elseBranch = ((JetIfExpression) sibling).getElse();
      if (elseBranch instanceof JetBlockExpression) {
        sibling = elseBranch;
      }
    }

    PsiElement start = sibling;
    PsiElement end = sibling;

    // moving out of code block
    if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)) {
      PsiElement parent = sibling.getParent();
      if (!(parent instanceof JetBlockExpression || parent instanceof JetFunctionLiteral))
        return null;

      JetBlockExpression newBlock;
      if (parent instanceof JetFunctionLiteral) {
        //noinspection ConstantConditions
        newBlock = findClosestBlock(((JetFunctionLiteral) parent).getBodyExpression(), down, false);

        if (!down) {
          ASTNode arrow = ((JetFunctionLiteral) parent).getArrowNode();
          if (arrow != null) {
            end = arrow.getPsi();
          }
        }
      } else {
        newBlock = findClosestBlock(sibling, down, true);
      }

      if (newBlock == null) return null;

      if (PsiTreeUtil.isAncestor(newBlock, parent, true)) {
        PsiElement outermostParent = JetPsiUtil.getOutermostParent(parent, newBlock, true);

        if (down) {
          end = outermostParent;
        } else {
          start = outermostParent;
        }
      } else {
        if (down) {
          end = newBlock.getLBrace();
        } else {
          start = newBlock.getRBrace();
        }
      }
    }
    // moving into code block
    else {
      PsiElement blockLikeElement;

      JetBlockExpression dslBlock = getDSLLambdaBlock(sibling, down);
      if (dslBlock != null) {
        // Use JetFunctionLiteral (since it contains braces)
        blockLikeElement = dslBlock.getParent();
      } else {
        // JetBlockExpression and other block-like elements
        blockLikeElement =
            JetPsiUtil.getOutermostDescendantElement(sibling, down, CHECK_BLOCK_LIKE_ELEMENT);
      }

      if (blockLikeElement != null) {
        if (down) {
          end = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.LBRACE);
          if (blockLikeElement instanceof JetFunctionLiteral) {
            ASTNode arrow = ((JetFunctionLiteral) blockLikeElement).getArrowNode();
            if (arrow != null) {
              end = arrow.getPsi();
            }
          }
        } else {
          start = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.RBRACE);
        }
      }
    }

    return start != null && end != null ? new LineRange(start, end, editor.getDocument()) : null;
  }
Esempio n. 11
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;
  }