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; }
/** 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; }
/** 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()]); }
@Override public void visitJetFile(JetFile file) { if (file.isScript()) { //noinspection ConstantConditions final ClassDescriptor classDescriptor = bindingContext.get(CLASS_FOR_FUNCTION, bindingContext.get(SCRIPT, file.getScript())); classStack.push(classDescriptor); //noinspection ConstantConditions nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName()); } else { nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/')); } file.acceptChildren(this); nameStack.pop(); if (file.isScript()) { classStack.pop(); } }
@NotNull public static Collection<JetFile> allFilesInNamespaces( BindingContext bindingContext, Collection<JetFile> files) { // todo: we use Set and add given files but ignoring other scripts because something non-clear // kept in binding // for scripts especially in case of REPL HashSet<FqName> names = new HashSet<FqName>(); for (JetFile file : files) { if (!file.isScript()) { names.add(JetPsiUtil.getFQName(file)); } } HashSet<JetFile> answer = new HashSet<JetFile>(); answer.addAll(files); for (FqName name : names) { NamespaceDescriptor namespaceDescriptor = bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, name); Collection<JetFile> jetFiles = bindingContext.get(NAMESPACE_TO_FILES, namespaceDescriptor); if (jetFiles != null) answer.addAll(jetFiles); } List<JetFile> sortedAnswer = new ArrayList<JetFile>(answer); Collections.sort( sortedAnswer, new Comparator<JetFile>() { @NotNull private String path(JetFile file) { VirtualFile virtualFile = file.getVirtualFile(); assert virtualFile != null : "VirtualFile is null for JetFile: " + file.getName(); return virtualFile.getPath(); } @Override public int compare(JetFile first, JetFile second) { return path(first).compareTo(path(second)); } }); return sortedAnswer; }
private static boolean compileBunchOfSources( K2JVMCompileEnvironmentConfiguration configuration, String jar, String outputDir, boolean includeRuntime) { FqName mainClass = null; for (JetFile file : configuration.getEnvironment().getSourceFiles()) { if (JetMainDetector.hasMain(file.getDeclarations())) { FqName fqName = JetPsiUtil.getFQName(file); mainClass = fqName.child(JvmAbi.PACKAGE_CLASS); break; } } GenerationState generationState = analyzeAndGenerate(configuration); if (generationState == null) { return false; } try { ClassFileFactory factory = generationState.getFactory(); if (jar != null) { try { CompileEnvironmentUtil.writeToJar( factory, new FileOutputStream(jar), mainClass, includeRuntime); } catch (FileNotFoundException e) { throw new CompileEnvironmentException("Invalid jar path " + jar, e); } } else if (outputDir != null) { CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir); } else { throw new CompileEnvironmentException( "Output directory or jar file is not specified - no files will be saved to the disk"); } return true; } finally { generationState.destroy(); } }
@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; }
private PsiJavaFileStub calcStub() { final PsiJavaFileStubImpl answer = new PsiJavaFileStubImpl(JetPsiUtil.getFQName(file), true); final Project project = getProject(); final Stack<StubElement> stubStack = new Stack<StubElement>(); final ClassBuilderFactory builderFactory = new ClassBuilderFactory() { @Override public ClassBuilder newClassBuilder() { return new StubClassBuilder(stubStack); } @Override public String asText(ClassBuilder builder) { throw new UnsupportedOperationException("asText is not implemented"); // TODO } @Override public byte[] asBytes(ClassBuilder builder) { throw new UnsupportedOperationException("asBytes is not implemented"); // TODO } }; final GenerationState state = new GenerationState(project, builderFactory) { @Override protected void generateNamespace(JetFile namespace) { PsiManager manager = PsiManager.getInstance(project); stubStack.push(answer); answer.setPsiFactory(new ClsWrapperStubPsiFactory()); final ClsFileImpl fakeFile = new ClsFileImpl( (PsiManagerImpl) manager, new ClassFileViewProvider(manager, file.getVirtualFile())) { @NotNull @Override public PsiClassHolderFileStub getStub() { return answer; } }; fakeFile.setPhysical(false); answer.setPsi(fakeFile); try { super.generateNamespace(namespace); } finally { final StubElement pop = stubStack.pop(); if (pop != answer) { LOG.error("Unbalanced stack operations: " + pop); } } } }; List<JetFile> files = Collections.singletonList(file); final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files); state.compileCorrectFiles(context, files); state.getFactory().files(); return answer; }