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; }
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; }
@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; }
/** 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); } }
// 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; }
@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(); }
/** 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()]); }
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; }
@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; }
@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; }
@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; }