Refactoring: "package matching directory" is now an inspection
This commit is contained in:
@@ -99,6 +99,7 @@ import org.jetbrains.kotlin.idea.highlighter.*
|
||||
import org.jetbrains.kotlin.idea.imports.AbstractJsOptimizeImportsTest
|
||||
import org.jetbrains.kotlin.idea.imports.AbstractJvmOptimizeImportsTest
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractLocalInspectionTest
|
||||
import org.jetbrains.kotlin.idea.inspections.AbstractMultiFileLocalInspectionTest
|
||||
import org.jetbrains.kotlin.idea.intentions.AbstractConcatenatedStringGeneratorTest
|
||||
import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest
|
||||
import org.jetbrains.kotlin.idea.intentions.AbstractIntentionTest2
|
||||
@@ -461,6 +462,10 @@ fun main(args: Array<String>) {
|
||||
model("multiFileIntentions", extension = "test", singleClass = true, filenameStartsLowerCase = true)
|
||||
}
|
||||
|
||||
testClass<AbstractMultiFileLocalInspectionTest> {
|
||||
model("multiFileLocalInspections", extension = "test", singleClass = true, filenameStartsLowerCase = true)
|
||||
}
|
||||
|
||||
testClass<AbstractMultiFileInspectionTest> {
|
||||
model("multiFileInspections", extension = "test", singleClass = true)
|
||||
}
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// File: bar/foo/test.kt
|
||||
<spot>package bar.foo</spot>
|
||||
|
||||
class MyClass: OtherClass {
|
||||
fun myFun() {
|
||||
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
// File: bar/foo/test.kt
|
||||
<spot>package foo.bar</spot>
|
||||
|
||||
import bar.foo.OtherClass
|
||||
|
||||
class MyClass: OtherClass {
|
||||
fun myFun() {
|
||||
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention changes file's package directive so that it matches containing directory.
|
||||
All import directives and usages are updated accordingly
|
||||
</body>
|
||||
</html>
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
// File: foo/bar/test.kt
|
||||
<spot>package foo.bar</spot>
|
||||
|
||||
import bar.foo.OtherClass
|
||||
|
||||
class MyClass: OtherClass {
|
||||
fun myFun() {
|
||||
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
// File: bar/foo/test.kt
|
||||
<spot>package foo.bar</spot>
|
||||
|
||||
import bar.foo.OtherClass
|
||||
|
||||
class MyClass: OtherClass {
|
||||
fun myFun() {
|
||||
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention moves file to the directory matching its package directive.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1142,16 +1142,6 @@
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.refactoring.move.changePackage.MoveFileToPackageMatchingDirectoryIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.refactoring.move.changePackage.ChangePackageToMatchDirectoryIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveDeclarationToSeparateFileIntention</className>
|
||||
<category>Kotlin</category>
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move.changePackage
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.idea.core.getFqNameByDirectory
|
||||
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingOffsetIndependentIntention
|
||||
import org.jetbrains.kotlin.idea.refactoring.hasIdentifiersOnly
|
||||
import org.jetbrains.kotlin.idea.refactoring.isInjectedFragment
|
||||
import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
|
||||
class ChangePackageToMatchDirectoryIntention : SelfTargetingOffsetIndependentIntention<KtPackageDirective>(
|
||||
KtPackageDirective::class.java, "", "Change file's package to match directory"
|
||||
) {
|
||||
override fun isApplicableTo(element: KtPackageDirective): Boolean {
|
||||
val file = element.containingKtFile
|
||||
if (file.isInjectedFragment || file.packageMatchesDirectory()) return false
|
||||
|
||||
val fqNameByDirectory = file.getFqNameByDirectory()
|
||||
text = if (!fqNameByDirectory.hasIdentifiersOnly()) {
|
||||
"File package doesn't match directory (cannot fix)"
|
||||
}
|
||||
else {
|
||||
"Change file's package to '${fqNameByDirectory.asString()}'"
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun applyTo(element: KtPackageDirective, editor: Editor?) {
|
||||
val file = element.containingKtFile
|
||||
val newFqName = file.getFqNameByDirectory()
|
||||
if (!newFqName.hasIdentifiersOnly()) return
|
||||
KotlinChangePackageRefactoring(file).run(newFqName)
|
||||
}
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move.changePackage
|
||||
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.roots.JavaProjectRootsUtil
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.refactoring.PackageWrapper
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.AutocreatingSingleSourceRootMoveDestination
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import com.intellij.refactoring.util.RefactoringMessageUtil
|
||||
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingOffsetIndependentIntention
|
||||
import org.jetbrains.kotlin.idea.refactoring.isInsideInjectedFragment
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
|
||||
class MoveFileToPackageMatchingDirectoryIntention : SelfTargetingOffsetIndependentIntention<KtPackageDirective>(
|
||||
KtPackageDirective::class.java, "", "Move file to package-matching directory"
|
||||
) {
|
||||
override fun isApplicableTo(element: KtPackageDirective): Boolean {
|
||||
if (element.isInsideInjectedFragment) return false
|
||||
if (element.containingKtFile.packageMatchesDirectory()) return false
|
||||
|
||||
val qualifiedName = element.qualifiedName
|
||||
val dirName = if (qualifiedName.isEmpty()) "source root" else "'${qualifiedName.replace('.', '/')}'"
|
||||
text = "Move file to $dirName"
|
||||
return true
|
||||
}
|
||||
|
||||
override fun startInWriteAction() = false
|
||||
|
||||
override fun applyTo(element: KtPackageDirective, editor: Editor?) {
|
||||
val file = element.containingKtFile
|
||||
val project = file.project
|
||||
|
||||
val sourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(project)
|
||||
val packageWrapper = PackageWrapper(PsiManager.getInstance(project), element.qualifiedName)
|
||||
val fileToMove = element.containingFile
|
||||
val chosenRoot =
|
||||
sourceRoots.singleOrNull()
|
||||
?: MoveClassesOrPackagesUtil.chooseSourceRoot(packageWrapper, sourceRoots, fileToMove.containingDirectory)
|
||||
?: return
|
||||
val targetDirFactory = AutocreatingSingleSourceRootMoveDestination(packageWrapper, chosenRoot)
|
||||
targetDirFactory.verify(fileToMove)?.let {
|
||||
Messages.showMessageDialog(project, it, CommonBundle.getErrorTitle(), Messages.getErrorIcon())
|
||||
return
|
||||
}
|
||||
val targetDirectory = runWriteAction {
|
||||
targetDirFactory.getTargetDirectory(fileToMove)
|
||||
} ?: return
|
||||
|
||||
RefactoringMessageUtil.checkCanCreateFile(targetDirectory, file.name)?.let {
|
||||
Messages.showMessageDialog(project, it, CommonBundle.getErrorTitle(), Messages.getErrorIcon())
|
||||
return
|
||||
}
|
||||
|
||||
runWriteAction {
|
||||
MoveFilesOrDirectoriesUtil.doMoveFile(file, targetDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
+102
-7
@@ -16,12 +16,107 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.refactoring.move.changePackage
|
||||
|
||||
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.codeInspection.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.JavaProjectRootsUtil
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.refactoring.PackageWrapper
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.AutocreatingSingleSourceRootMoveDestination
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil
|
||||
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
|
||||
import com.intellij.refactoring.util.RefactoringMessageUtil
|
||||
import org.jetbrains.kotlin.idea.core.getFqNameByDirectory
|
||||
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
||||
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.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
import org.jetbrains.kotlin.psi.KtVisitorVoid
|
||||
|
||||
class PackageDirectoryMismatchInspection: IntentionBasedInspection<KtPackageDirective>(
|
||||
listOf(
|
||||
IntentionBasedInspection.IntentionData(MoveFileToPackageMatchingDirectoryIntention::class),
|
||||
IntentionBasedInspection.IntentionData(ChangePackageToMatchDirectoryIntention::class)),
|
||||
"Package directive doesn't match file location"
|
||||
)
|
||||
class PackageDirectoryMismatchInspection : AbstractKotlinInspection() {
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession) =
|
||||
object : KtVisitorVoid() {
|
||||
override fun visitPackageDirective(directive: KtPackageDirective) {
|
||||
super.visitPackageDirective(directive)
|
||||
if (directive.text.isEmpty()) return
|
||||
|
||||
val file = directive.containingKtFile
|
||||
if (file.isInjectedFragment || file.packageMatchesDirectory()) return
|
||||
|
||||
val fixes = mutableListOf<LocalQuickFix>()
|
||||
val qualifiedName = directive.qualifiedName
|
||||
val dirName = if (qualifiedName.isEmpty()) "source root" else "'${qualifiedName.replace('.', '/')}'"
|
||||
fixes += MoveFileToPackageFix(dirName)
|
||||
val fqNameByDirectory = file.getFqNameByDirectory()
|
||||
if (fqNameByDirectory.hasIdentifiersOnly()) {
|
||||
fixes += ChangePackageFix(fqNameByDirectory)
|
||||
}
|
||||
|
||||
holder.registerProblem(
|
||||
directive,
|
||||
"Package directive doesn't match file location",
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
*fixes.toTypedArray()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class MoveFileToPackageFix(val dirName: String) : LocalQuickFix {
|
||||
override fun getFamilyName() = "Move file to package-matching directory"
|
||||
|
||||
override fun getName() = "Move file to $dirName"
|
||||
|
||||
override fun startInWriteAction() = false
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val directive = descriptor.psiElement as? KtPackageDirective ?: return
|
||||
val file = directive.containingKtFile
|
||||
|
||||
val sourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(project)
|
||||
val packageWrapper = PackageWrapper(PsiManager.getInstance(project), directive.qualifiedName)
|
||||
val fileToMove = directive.containingFile
|
||||
val chosenRoot =
|
||||
sourceRoots.singleOrNull()
|
||||
?: MoveClassesOrPackagesUtil.chooseSourceRoot(packageWrapper, sourceRoots,
|
||||
fileToMove.containingDirectory)
|
||||
?: return
|
||||
val targetDirFactory = AutocreatingSingleSourceRootMoveDestination(packageWrapper, chosenRoot)
|
||||
targetDirFactory.verify(fileToMove)?.let {
|
||||
Messages.showMessageDialog(project, it, CommonBundle.getErrorTitle(), Messages.getErrorIcon())
|
||||
return
|
||||
}
|
||||
val targetDirectory = runWriteAction {
|
||||
targetDirFactory.getTargetDirectory(fileToMove)
|
||||
} ?: return
|
||||
|
||||
RefactoringMessageUtil.checkCanCreateFile(targetDirectory, file.name)?.let {
|
||||
Messages.showMessageDialog(project, it, CommonBundle.getErrorTitle(), Messages.getErrorIcon())
|
||||
return
|
||||
}
|
||||
|
||||
runWriteAction {
|
||||
MoveFilesOrDirectoriesUtil.doMoveFile(file, targetDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ChangePackageFix(val fqNameByDirectory: FqName) : LocalQuickFix {
|
||||
override fun getFamilyName() = "Change file's package to match directory"
|
||||
|
||||
override fun getName() = "Change file's package to '${fqNameByDirectory.asString()}'"
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val directive = descriptor.psiElement as? KtPackageDirective ?: return
|
||||
val file = directive.containingKtFile
|
||||
val newFqName = file.getFqNameByDirectory()
|
||||
if (!newFqName.hasIdentifiersOnly()) return
|
||||
KotlinChangePackageRefactoring(file).run(newFqName)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"mainFile": "source/test.kt",
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.MoveFileToPackageMatchingDirectoryIntention",
|
||||
"intentionText": "Move file to source root"
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"mainFile": "source/test.kt",
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.MoveFileToPackageMatchingDirectoryIntention",
|
||||
"intentionText": "Move file to 'target'"
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.MoveFileToPackageMatchingDirectoryIntention",
|
||||
"isApplicable": "false",
|
||||
"mainFile": "foo/bar/test.kt"
|
||||
}
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"mainFile": "in/foo/fun/test.kt",
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.ChangePackageToMatchDirectoryIntention",
|
||||
"intentionText": "Change file's package to 'in.foo.fun'"
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"mainFile": "test.kt",
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.ChangePackageToMatchDirectoryIntention",
|
||||
"intentionText": "Change file's package to ''"
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"mainFile": "target/test.kt",
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.ChangePackageToMatchDirectoryIntention",
|
||||
"intentionText": "Change file's package to 'target'"
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.ChangePackageToMatchDirectoryIntention",
|
||||
"isApplicable": "true",
|
||||
"mainFile": "foo/test.kt"
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.ChangePackageToMatchDirectoryIntention",
|
||||
"isApplicable": "false",
|
||||
"mainFile": "foo/bar/test.kt"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "source/test.kt",
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"fix": "Move file to source root"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "source/test.kt",
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"fix": "Move file to 'target'"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"problem": "none",
|
||||
"mainFile": "foo/bar/test.kt"
|
||||
}
|
||||
idea/testData/multiFileLocalInspections/reconcilePackageWithDirectory/addQuotation/addQuotation.test
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "in/foo/fun/test.kt",
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"fix": "Change file's package to 'in.foo.fun'"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "test.kt",
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"fix": "Change file's package to ''"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "target/test.kt",
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"fix": "Change file's package to 'target'"
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"mainFile": "foo/test.kt",
|
||||
"fix": "Change file's package to 'foo'"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"inspectionClass": "org.jetbrains.kotlin.idea.refactoring.move.changePackage.PackageDirectoryMismatchInspection",
|
||||
"problem": "none",
|
||||
"mainFile": "foo/bar/test.kt"
|
||||
}
|
||||
@@ -75,7 +75,7 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
|
||||
return Class.forName(className).newInstance() as AbstractKotlinInspection
|
||||
}
|
||||
|
||||
protected fun doTest(path: String) {
|
||||
protected open fun doTest(path: String) {
|
||||
val mainFile = File(path)
|
||||
val inspection = createInspection(mainFile)
|
||||
|
||||
@@ -114,13 +114,14 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
|
||||
}
|
||||
}
|
||||
|
||||
private fun doTestFor(mainFilePath: String, file: VirtualFile, inspection: AbstractKotlinInspection, fileText: String) {
|
||||
val problemExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
|
||||
fileText, "// $expectedProblemDirectiveName: ")
|
||||
protected fun runInspectionWithFixesAndCheck(
|
||||
file: VirtualFile,
|
||||
inspection: AbstractKotlinInspection,
|
||||
problemExpectedString: String?,
|
||||
highlightExpectedString: String?,
|
||||
localFixTextString: String?
|
||||
): Boolean {
|
||||
val problemExpected = problemExpectedString == null || problemExpectedString != "none"
|
||||
val highlightExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
|
||||
fileText, "// $expectedProblemHighlightType: ")
|
||||
|
||||
val presentation = runInspection(inspection, project, listOf(file))
|
||||
val problemDescriptors = presentation.problemDescriptors
|
||||
.filterIsInstance<ProblemDescriptor>()
|
||||
@@ -135,7 +136,7 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
|
||||
else
|
||||
"Expected at least one problem at caret",
|
||||
problemExpected == problemDescriptors.isNotEmpty())
|
||||
if (!problemExpected) return
|
||||
if (!problemExpected) return false
|
||||
if (problemExpectedString != null) {
|
||||
Assert.assertTrue("Expected the following problem at caret: $problemExpectedString\n" +
|
||||
"Active problems: ${problemDescriptors.joinToString { it.descriptionTemplate }}",
|
||||
@@ -147,9 +148,7 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
|
||||
problemDescriptors.all { it.highlightType.toString() == highlightExpectedString })
|
||||
}
|
||||
|
||||
val localFixTextString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// $fixTextDirectiveName: ")
|
||||
val localFixActions = problemDescriptors.flatMap {
|
||||
problem ->
|
||||
val localFixActions = problemDescriptors.flatMap { problem ->
|
||||
val fixes = problem.fixes
|
||||
fixes?.toList() ?: emptyList()
|
||||
}.filter { fix -> localFixTextString == null || fix.name == localFixTextString }
|
||||
@@ -171,6 +170,21 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
|
||||
project.executeWriteCommand(localFixAction!!.name, null) {
|
||||
localFixAction.applyFix(project, problemDescriptor)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun doTestFor(mainFilePath: String, file: VirtualFile, inspection: AbstractKotlinInspection, fileText: String) {
|
||||
val problemExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
|
||||
fileText, "// $expectedProblemDirectiveName: ")
|
||||
val highlightExpectedString = InTextDirectivesUtils.findStringWithPrefixes(
|
||||
fileText, "// $expectedProblemHighlightType: ")
|
||||
val localFixTextString = InTextDirectivesUtils.findStringWithPrefixes(
|
||||
fileText, "// $fixTextDirectiveName: ")
|
||||
|
||||
if (!runInspectionWithFixesAndCheck(file, inspection, problemExpectedString, highlightExpectedString, localFixTextString)) {
|
||||
return
|
||||
}
|
||||
|
||||
val canonicalPathToExpectedFile = mainFilePath + afterFileNameSuffix
|
||||
try {
|
||||
myFixture.checkResultByFile(canonicalPathToExpectedFile)
|
||||
@@ -182,6 +196,7 @@ abstract class AbstractLocalInspectionTest : KotlinLightCodeInsightFixtureTestCa
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val EXTENSIONS = arrayOf(".kt", ".kts", ".java", ".groovy")
|
||||
}
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.idea.jsonUtils.getString
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractMultiFileLocalInspectionTest : AbstractLocalInspectionTest() {
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor {
|
||||
if (KotlinTestUtils.isAllFilesPresentTest(getTestName(false))) return super.getProjectDescriptor()
|
||||
val testFile = File(testDataPath, fileName())
|
||||
val config = JsonParser().parse(FileUtil.loadFile(testFile, true)) as JsonObject
|
||||
val withRuntime = config["withRuntime"]?.asBoolean ?: false
|
||||
return if (withRuntime)
|
||||
KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||
else
|
||||
KotlinLightProjectDescriptor.INSTANCE
|
||||
}
|
||||
|
||||
override fun doTest(path: String) {
|
||||
val testFile = File(path)
|
||||
val config = JsonParser().parse(FileUtil.loadFile(testFile, true)) as JsonObject
|
||||
|
||||
val mainFilePath = config.getString("mainFile")
|
||||
val mainFile = File(testFile.parent, "before/$mainFilePath")
|
||||
val mainFileText = FileUtil.loadFile(mainFile, true)
|
||||
TestCase.assertTrue("\"<caret>\" is missing in file \"$mainFilePath\"", mainFileText.contains("<caret>"))
|
||||
|
||||
val inspection = Class.forName(config.getString("inspectionClass")).newInstance() as AbstractKotlinInspection
|
||||
val problemExpectedString = config["problem"]?.asString // null means "some problem", "none" means no problem
|
||||
val localFixTextString = config["fix"]?.asString // null means "some single fix" or "none" if no problem expected
|
||||
|
||||
doTest(path) test@ { _ ->
|
||||
val mainFile = myFixture.configureFromTempProjectFile(mainFilePath)
|
||||
|
||||
runInspectionWithFixesAndCheck(mainFile.virtualFile, inspection, problemExpectedString, null, localFixTextString)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun doTest(path: String, action: (VirtualFile) -> Unit) {
|
||||
val beforeDir = path.removePrefix(testDataPath).substringBeforeLast('/') + "/before"
|
||||
val beforeVFile = myFixture.copyDirectoryToProject(beforeDir, "")
|
||||
PsiDocumentManager.getInstance(myFixture.project).commitAllDocuments()
|
||||
|
||||
val afterDir = beforeDir.substringBeforeLast("/") + "/after"
|
||||
val afterDirIOFile = File(testDataPath, afterDir)
|
||||
val afterVFile = LocalFileSystem.getInstance().findFileByIoFile(afterDirIOFile)!!
|
||||
UsefulTestCase.refreshRecursively(afterVFile)
|
||||
|
||||
action(beforeVFile)
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
FileDocumentManager.getInstance().saveAllDocuments()
|
||||
PlatformTestUtil.assertDirectoriesEqual(afterVFile, beforeVFile)
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/multiFileLocalInspections")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class MultiFileLocalInspectionTestGenerated extends AbstractMultiFileLocalInspectionTest {
|
||||
public void testAllFilesPresentInMultiFileLocalInspections() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/multiFileLocalInspections"), Pattern.compile("^(.+)\\.test$"), TargetBackend.ANY);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileToPackageMatchingDirectory/moveToDefaultDirectory/moveToDefaultDirectory.test")
|
||||
public void testMoveFileToPackageMatchingDirectory_moveToDefaultDirectory_MoveToDefaultDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/moveFileToPackageMatchingDirectory/moveToDefaultDirectory/moveToDefaultDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileToPackageMatchingDirectory/moveToNonDefaultDirectory/moveToNonDefaultDirectory.test")
|
||||
public void testMoveFileToPackageMatchingDirectory_moveToNonDefaultDirectory_MoveToNonDefaultDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/moveFileToPackageMatchingDirectory/moveToNonDefaultDirectory/moveToNonDefaultDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileToPackageMatchingDirectory/packageMatchesDirectory/packageMatchesDirectory.test")
|
||||
public void testMoveFileToPackageMatchingDirectory_packageMatchesDirectory_PackageMatchesDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/moveFileToPackageMatchingDirectory/packageMatchesDirectory/packageMatchesDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/addQuotation/addQuotation.test")
|
||||
public void testReconcilePackageWithDirectory_addQuotation_AddQuotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/reconcilePackageWithDirectory/addQuotation/addQuotation.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/changeToDefaultPackage/changeToDefaultPackage.test")
|
||||
public void testReconcilePackageWithDirectory_changeToDefaultPackage_ChangeToDefaultPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/reconcilePackageWithDirectory/changeToDefaultPackage/changeToDefaultPackage.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/changeToNonDefaultPackage/changeToNonDefaultPackage.test")
|
||||
public void testReconcilePackageWithDirectory_changeToNonDefaultPackage_ChangeToNonDefaultPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/reconcilePackageWithDirectory/changeToNonDefaultPackage/changeToNonDefaultPackage.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/innerClass/innerClass.test")
|
||||
public void testReconcilePackageWithDirectory_innerClass_InnerClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/reconcilePackageWithDirectory/innerClass/innerClass.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/packageMatchesDirectory/packageMatchesDirectory.test")
|
||||
public void testReconcilePackageWithDirectory_packageMatchesDirectory_PackageMatchesDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileLocalInspections/reconcilePackageWithDirectory/packageMatchesDirectory/packageMatchesDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
@@ -132,24 +132,6 @@ public class MultiFileIntentionTestGenerated extends AbstractMultiFileIntentionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileToPackageMatchingDirectory/moveToDefaultDirectory/moveToDefaultDirectory.test")
|
||||
public void testMoveFileToPackageMatchingDirectory_moveToDefaultDirectory_MoveToDefaultDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/moveFileToPackageMatchingDirectory/moveToDefaultDirectory/moveToDefaultDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileToPackageMatchingDirectory/moveToNonDefaultDirectory/moveToNonDefaultDirectory.test")
|
||||
public void testMoveFileToPackageMatchingDirectory_moveToNonDefaultDirectory_MoveToNonDefaultDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/moveFileToPackageMatchingDirectory/moveToNonDefaultDirectory/moveToNonDefaultDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveFileToPackageMatchingDirectory/packageMatchesDirectory/packageMatchesDirectory.test")
|
||||
public void testMoveFileToPackageMatchingDirectory_packageMatchesDirectory_PackageMatchesDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/moveFileToPackageMatchingDirectory/packageMatchesDirectory/packageMatchesDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("moveOutOfCompanion/moveClass/moveClass.test")
|
||||
public void testMoveOutOfCompanion_moveClass_MoveClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/moveOutOfCompanion/moveClass/moveClass.test");
|
||||
@@ -185,34 +167,4 @@ public class MultiFileIntentionTestGenerated extends AbstractMultiFileIntentionT
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/objectLiteralToLambda/objectLiteralToLambda.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/addQuotation/addQuotation.test")
|
||||
public void testReconcilePackageWithDirectory_addQuotation_AddQuotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/reconcilePackageWithDirectory/addQuotation/addQuotation.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/changeToDefaultPackage/changeToDefaultPackage.test")
|
||||
public void testReconcilePackageWithDirectory_changeToDefaultPackage_ChangeToDefaultPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/reconcilePackageWithDirectory/changeToDefaultPackage/changeToDefaultPackage.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/changeToNonDefaultPackage/changeToNonDefaultPackage.test")
|
||||
public void testReconcilePackageWithDirectory_changeToNonDefaultPackage_ChangeToNonDefaultPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/reconcilePackageWithDirectory/changeToNonDefaultPackage/changeToNonDefaultPackage.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/innerClass/innerClass.test")
|
||||
public void testReconcilePackageWithDirectory_innerClass_InnerClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/reconcilePackageWithDirectory/innerClass/innerClass.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reconcilePackageWithDirectory/packageMatchesDirectory/packageMatchesDirectory.test")
|
||||
public void testReconcilePackageWithDirectory_packageMatchesDirectory_PackageMatchesDirectory() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/multiFileIntentions/reconcilePackageWithDirectory/packageMatchesDirectory/packageMatchesDirectory.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user