diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt index 9ab18a8fcc4..2c93fa0c6c0 100644 --- a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt +++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt @@ -22,4 +22,6 @@ object ResourceKotlinRootType : KotlinResourceRootType() object TestResourceKotlinRootType : KotlinResourceRootType() { override fun isForTests() = true -} \ No newline at end of file +} + +val ALL_KOTLIN_RESOURCE_ROOT_TYPES = setOf(ResourceKotlinRootType, TestResourceKotlinRootType) \ No newline at end of file diff --git a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.182 b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.182 index 02d85caeaf0..68a27ba200a 100644 --- a/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.182 +++ b/idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinResourceRootType.kt.182 @@ -23,4 +23,6 @@ sealed class KotlinResourceRootType(val isTest: Boolean) : JpsElementTypeBase 1 + val isMultipleSourceRoots = getSuitableDestinationSourceRoots(project).size > 1 destinationComboBox.isVisible = isMultipleSourceRoots label.isVisible = isMultipleSourceRoots label.labelFor = destinationComboBox diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt index 60a1b5024a3..77eff9d9519 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt @@ -25,7 +25,6 @@ import com.intellij.openapi.editor.markup.RangeHighlighter import com.intellij.openapi.editor.markup.TextAttributes import com.intellij.openapi.options.ConfigurationException import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.JavaProjectRootsUtil import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.popup.* @@ -75,6 +74,7 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar import org.jetbrains.kotlin.idea.refactoring.changeSignature.toValVar import org.jetbrains.kotlin.idea.refactoring.memberInfo.KtPsiClassWrapper import org.jetbrains.kotlin.idea.refactoring.rename.canonicalRender +import org.jetbrains.kotlin.idea.roots.isOutsideKotlinAwareSourceRoot import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.idea.util.actualsForExpected @@ -138,8 +138,8 @@ fun PsiElement.getUsageContext(): PsiElement { } } -fun PsiElement.isInJavaSourceRoot(): Boolean = - !JavaProjectRootsUtil.isOutsideJavaSourceRoot(containingFile) +fun PsiElement.isInKotlinAwareSourceRoot(): Boolean = + !isOutsideKotlinAwareSourceRoot(containingFile) fun KtFile.createTempCopy(text: String? = null): KtFile { val tmpFile = KtPsiFactory(this).createAnalyzableFile(name, text ?: this.text ?: "", this) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt index 5868f612327..5e9dcbe13e4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/changePackage/PackageDirectoryMismatchInspection.kt @@ -10,7 +10,6 @@ import com.intellij.codeInspection.LocalQuickFix import com.intellij.codeInspection.ProblemDescriptor import com.intellij.codeInspection.ProblemsHolder import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.JavaProjectRootsUtil import com.intellij.openapi.ui.Messages import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiManager @@ -25,6 +24,7 @@ import org.jetbrains.kotlin.idea.core.packageMatchesDirectoryOrImplicit import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection import org.jetbrains.kotlin.idea.refactoring.hasIdentifiersOnly import org.jetbrains.kotlin.idea.refactoring.isInjectedFragment +import org.jetbrains.kotlin.idea.roots.getSuitableDestinationSourceRoots import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile @@ -75,7 +75,7 @@ class PackageDirectoryMismatchInspection : AbstractKotlinInspection() { val file = descriptor.psiElement as? KtFile ?: return val directive = file.packageDirective ?: return - val sourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(project) + val sourceRoots = getSuitableDestinationSourceRoots(project) val packageWrapper = PackageWrapper(PsiManager.getInstance(project), directive.qualifiedName) val fileToMove = directive.containingFile val chosenRoot = diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/KotlinAwareMoveFilesOrDirectoriesDialog.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/KotlinAwareMoveFilesOrDirectoriesDialog.kt index fd40e82dadd..bc396e73565 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/KotlinAwareMoveFilesOrDirectoriesDialog.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/KotlinAwareMoveFilesOrDirectoriesDialog.kt @@ -33,7 +33,7 @@ import com.intellij.util.ui.FormBuilder import com.intellij.util.ui.UIUtil import org.jetbrains.kotlin.idea.core.packageMatchesDirectoryOrImplicit import org.jetbrains.kotlin.idea.core.util.onTextChange -import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot +import org.jetbrains.kotlin.idea.refactoring.isInKotlinAwareSourceRoot import org.jetbrains.kotlin.idea.util.application.executeCommand import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.psi.KtFile @@ -131,7 +131,8 @@ class KotlinAwareMoveFilesOrDirectoriesDialog( this.helpID = helpID with(updatePackageDirectiveCb) { - val jetFiles = psiElements.filterIsInstance().filter(KtFile::isInJavaSourceRoot) + val jetFiles = psiElements.filterIsInstance().filter(KtFile::isInKotlinAwareSourceRoot) + if (jetFiles.isEmpty()) { parent.remove(updatePackageDirectiveCb) return diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinNestedClassesToUpperLevelDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinNestedClassesToUpperLevelDialog.java index d0aaddd1381..9ce4cef6421 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinNestedClassesToUpperLevelDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinNestedClassesToUpperLevelDialog.java @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.JavaProjectRootsUtil; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.NullableComputable; @@ -52,6 +51,7 @@ import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode; import org.jetbrains.kotlin.types.KotlinType; +import static org.jetbrains.kotlin.idea.roots.ProjectRootUtilsKt.getSuitableDestinationSourceRoots; import javax.swing.*; import java.awt.*; @@ -244,9 +244,11 @@ public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase { String targetName = packageNameField.getText(); if (!Comparing.equal(oldPackageFqName != null ? oldPackageFqName.asString() : null, targetName)) { ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project); - List contentSourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(project); + + List contentSourceRoots = getSuitableDestinationSourceRoots(project); PackageWrapper newPackage = new PackageWrapper(PsiManager.getInstance(project), targetName); VirtualFile targetSourceRoot; + if (contentSourceRoots.size() > 1) { PsiDirectory initialDir = null; PsiPackage oldPackage = oldPackageFqName != null diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java index cf92f49a432..b0e0aa2f5ae 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java @@ -13,7 +13,6 @@ import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.JavaProjectRootsUtil; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Pair; @@ -61,6 +60,7 @@ import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtNamedDeclaration; import org.jetbrains.kotlin.psi.KtPureElement; import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; +import static org.jetbrains.kotlin.idea.roots.ProjectRootUtilsKt.getSuitableDestinationSourceRoots; import javax.swing.*; import java.awt.*; @@ -396,7 +396,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog { } private boolean hasAnySourceRoots() { - return !JavaProjectRootsUtil.getSuitableDestinationSourceRoots(myProject).isEmpty(); + return !getSuitableDestinationSourceRoots(myProject).isEmpty(); } private void saveRefactoringSettings() { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt index 3cbbcf72b5c..488c5f8e4b5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories import com.intellij.openapi.module.ModuleUtilCore -import com.intellij.openapi.roots.JavaProjectRootsUtil import com.intellij.openapi.util.Key import com.intellij.psi.PsiCompiledElement import com.intellij.psi.PsiDirectory @@ -25,6 +24,7 @@ import org.jetbrains.kotlin.idea.refactoring.move.ContainerChangeInfo import org.jetbrains.kotlin.idea.refactoring.move.ContainerInfo import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.* import org.jetbrains.kotlin.idea.refactoring.move.updatePackageDirective +import org.jetbrains.kotlin.idea.roots.isOutsideKotlinAwareSourceRoot import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.UserDataProperty @@ -93,7 +93,7 @@ class MoveKotlinFileHandler : MoveFileHandler() { override fun canProcessElement(element: PsiFile?): Boolean { if (element is PsiCompiledElement || element !is KtFile) return false - return !JavaProjectRootsUtil.isOutsideJavaSourceRoot(element) + return !isOutsideKotlinAwareSourceRoot(element) } override fun findUsages( diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesUtil.kt index ea3c6898d13..50f300c979e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesUtil.kt @@ -29,7 +29,7 @@ import com.intellij.refactoring.move.MoveHandler import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.util.IncorrectOperationException -import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot +import org.jetbrains.kotlin.idea.refactoring.isInKotlinAwareSourceRoot import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.KotlinAwareMoveFilesOrDirectoriesProcessor import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog import org.jetbrains.kotlin.idea.util.application.executeCommand @@ -71,7 +71,7 @@ fun invokeMoveFilesOrDirectoriesRefactoring( elementsToMove.forEach { MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir) - if (it is KtFile && it.isInJavaSourceRoot()) { + if (it is KtFile && it.isInKotlinAwareSourceRoot()) { it.updatePackageDirective = updatePackageDirective } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/CreateKotlinClassDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/CreateKotlinClassDialog.java index 9b2216cb3fd..6b5a41690a6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/CreateKotlinClassDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/CreateKotlinClassDialog.java @@ -16,7 +16,6 @@ import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.JavaProjectRootsUtil; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Pass; @@ -39,6 +38,7 @@ import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static org.jetbrains.kotlin.idea.roots.ProjectRootUtilsKt.getSuitableDestinationSourceRoots; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -198,7 +198,7 @@ public class CreateKotlinClassDialog extends DialogWrapper { gbConstraints.insets.top = 4; panel.add(myDestinationCB, gbConstraints); - boolean isMultipleSourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(myProject).size() > 1; + boolean isMultipleSourceRoots = getSuitableDestinationSourceRoots(myProject).size() > 1; myDestinationCB.setVisible(isMultipleSourceRoots); label.setVisible(isMultipleSourceRoots); label.setLabelFor(myDestinationCB); diff --git a/idea/src/org/jetbrains/kotlin/idea/roots/projectRootUtils.kt b/idea/src/org/jetbrains/kotlin/idea/roots/projectRootUtils.kt index 8f7db34f64f..ce189dd532f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/roots/projectRootUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/roots/projectRootUtils.kt @@ -9,19 +9,23 @@ import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project import com.intellij.openapi.project.rootManager -import com.intellij.openapi.roots.JavaProjectRootsUtil.isForGeneratedSources import com.intellij.openapi.roots.ModifiableRootModel +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.roots.SourceFolder +import com.intellij.openapi.vfs.NonPhysicalFileSystem import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiCodeFragment +import com.intellij.psi.PsiFile +import com.intellij.util.containers.ContainerUtil import org.jetbrains.jps.model.JpsElement import org.jetbrains.jps.model.ex.JpsElementBase -import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes -import org.jetbrains.jps.model.java.JavaResourceRootType -import org.jetbrains.jps.model.java.JavaSourceRootProperties -import org.jetbrains.jps.model.java.JavaSourceRootType +import org.jetbrains.jps.model.java.* import org.jetbrains.jps.model.module.JpsModuleSourceRoot import org.jetbrains.jps.model.module.JpsModuleSourceRootType import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.idea.framework.KotlinSdkType +import java.util.ArrayList private fun JpsModuleSourceRoot.getOrCreateProperties() = getProperties(rootType)?.also { (it as? JpsElementBase<*>)?.setParent(null) } ?: rootType.createDefaultProperties() @@ -66,4 +70,46 @@ private fun Module.collectKotlinAwareDestinationSourceRoots(): List .filterNot { isForGeneratedSources(it) } .mapNotNull { it.file } .toList() -} \ No newline at end of file +} + +fun isOutsideSourceRootSet(psiFile : PsiFile?, sourceRootTypes: Set>): Boolean { + if (psiFile == null) return false + if (psiFile is PsiCodeFragment) return false + val file = psiFile.getVirtualFile() + if (file == null) return false + if (file.getFileSystem() is NonPhysicalFileSystem) return false + val projectFileIndex = ProjectRootManager.getInstance(psiFile.getProject()).getFileIndex() + return !projectFileIndex.isUnderSourceRootOfType(file, sourceRootTypes) && !projectFileIndex.isInLibrary(file) +} + +fun isOutsideKotlinAwareSourceRoot(psiFile : PsiFile?) = isOutsideSourceRootSet(psiFile, KOTLIN_AWARE_SOURCE_ROOT_TYPES) + +/** + * @return list of all java source roots in the project which can be suggested as a target directory for a class created by user + */ +fun getSuitableDestinationSourceRoots(project: Project): List { + val roots = ArrayList() + for (module in ModuleManager.getInstance(project).modules) { + collectSuitableDestinationSourceRoots(module, roots) + } + return roots +} + +fun collectSuitableDestinationSourceRoots(module: Module, result: MutableList) { + for (entry in ModuleRootManager.getInstance(module).contentEntries) { + for (sourceFolder in entry.getSourceFolders(KOTLIN_AWARE_SOURCE_ROOT_TYPES)) { + if (!isForGeneratedSources(sourceFolder)) { + ContainerUtil.addIfNotNull(result, sourceFolder.file) + } + } + } +} + +fun isForGeneratedSources(sourceFolder: SourceFolder): Boolean { + val properties = sourceFolder.jpsElement.getProperties(KOTLIN_AWARE_SOURCE_ROOT_TYPES) + val javaResourceProperties = sourceFolder.jpsElement.getProperties(JavaModuleSourceRootTypes.RESOURCES) + val kotlinResourceProperties = sourceFolder.jpsElement.getProperties(ALL_KOTLIN_RESOURCE_ROOT_TYPES) + return properties != null && properties.isForGeneratedSources + || (javaResourceProperties != null && javaResourceProperties.isForGeneratedSources) + || (kotlinResourceProperties != null && kotlinResourceProperties.isForGeneratedSources) +}