Code style setting to import nested classes

This commit is contained in:
Valentin Kipyatkov
2015-04-10 18:52:10 +03:00
parent be896b7d8e
commit 0f9858bb75
8 changed files with 51 additions and 27 deletions
@@ -44,6 +44,7 @@ public class JetCodeStyleSettings extends CustomCodeStyleSettings {
public int NAME_COUNT_TO_USE_STAR_IMPORT = ApplicationManager.getApplication().isUnitTestMode() ? Integer.MAX_VALUE : 5; public int NAME_COUNT_TO_USE_STAR_IMPORT = ApplicationManager.getApplication().isUnitTestMode() ? Integer.MAX_VALUE : 5;
public boolean IMPORT_PACKAGES = true; public boolean IMPORT_PACKAGES = true;
public boolean IMPORT_NESTED_CLASSES = false;
public static JetCodeStyleSettings getInstance(Project project) { public static JetCodeStyleSettings getInstance(Project project) {
return CodeStyleSettingsManager.getSettings(project).getCustomSettings(JetCodeStyleSettings.class); return CodeStyleSettingsManager.getSettings(project).getCustomSettings(JetCodeStyleSettings.class);
@@ -139,13 +139,18 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
val importable = descriptor.getImportableDescriptor() val importable = descriptor.getImportableDescriptor()
return when (importable) { return when (importable) {
is PackageViewDescriptor -> JetCodeStyleSettings.getInstance(project).IMPORT_PACKAGES is PackageViewDescriptor -> JetCodeStyleSettings.getInstance(project).IMPORT_PACKAGES
else -> importable.getContainingDeclaration() is PackageFragmentDescriptor // do not import nested classes and non-top-level declarations
is ClassDescriptor -> {
importable.getContainingDeclaration() is PackageFragmentDescriptor
|| JetCodeStyleSettings.getInstance(project).IMPORT_NESTED_CLASSES
}
else -> importable.getContainingDeclaration() is PackageFragmentDescriptor // do not import members (e.g. java static members)
} }
} }
override fun importDescriptor(file: JetFile, descriptor: DeclarationDescriptor): ImportDescriptorResult { override fun importDescriptor(file: JetFile, descriptor: DeclarationDescriptor)
return Importer(file).importDescriptor(descriptor) = Importer(file).importDescriptor(descriptor)
}
private inner class Importer( private inner class Importer(
private val file: JetFile private val file: JetFile
@@ -155,11 +160,11 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
fun importDescriptor(descriptor: DeclarationDescriptor): ImportDescriptorResult { fun importDescriptor(descriptor: DeclarationDescriptor): ImportDescriptorResult {
val target = descriptor.getImportableDescriptor() val target = descriptor.getImportableDescriptor()
if (!target.canBeReferencedViaImport()) return ImportDescriptorResult.FAIL
val name = target.getName() val name = target.getName()
val topLevelScope = resolutionFacade.getFileTopLevelScope(file) val topLevelScope = resolutionFacade.getFileTopLevelScope(file)
val targetFqName = target.importableFqNameSafe
val targetFqName = target.importableFqName ?: return ImportDescriptorResult.FAIL
// check if import is not needed // check if import is not needed
when (target) { when (target) {
@@ -174,11 +179,6 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
return ImportDescriptorResult.FAIL return ImportDescriptorResult.FAIL
} }
// cannot import for non-top level function or property
if (target is CallableDescriptor && target.getContainingDeclaration() !is PackageFragmentDescriptor) {
return ImportDescriptorResult.FAIL
}
val imports = if (file is JetCodeFragment) val imports = if (file is JetCodeFragment)
file.importsAsImportList()?.getImports() ?: listOf() file.importsAsImportList()?.getImports() ?: listOf()
else else
@@ -379,16 +379,13 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
return result return result
} }
private fun targetFqName(ref: JetReferenceExpression): FqName? { private fun targetFqName(ref: JetReferenceExpression): FqName?
return ref.resolveTargets().map { it.importableFqName }.toSet().singleOrNull() = ref.resolveTargets().map { it.importableFqName }.toSet().singleOrNull()
}
private fun JetReferenceExpression.resolveTargets(): Collection<DeclarationDescriptor> { private fun JetReferenceExpression.resolveTargets(): Collection<DeclarationDescriptor>
return this.getImportableTargets(resolutionFacade.analyze(this, BodyResolveMode.PARTIAL)) = this.getImportableTargets(resolutionFacade.analyze(this, BodyResolveMode.PARTIAL))
}
private fun addImport(fqName: FqName, allUnder: Boolean): JetImportDirective { private fun addImport(fqName: FqName, allUnder: Boolean): JetImportDirective
return addImport(file, ImportPath(fqName, allUnder)) = addImport(file, ImportPath(fqName, allUnder))
}
} }
} }
@@ -0,0 +1 @@
// IMPORT: kotlin.Map.Entry
@@ -0,0 +1 @@
Failed to add import
@@ -0,0 +1,2 @@
// IMPORT: kotlin.Map.Entry
// IMPORT_NESTED_CLASSES: true
@@ -0,0 +1,4 @@
import kotlin.Map.*
// IMPORT: kotlin.Map.Entry
// IMPORT_NESTED_CLASSES: true
@@ -17,11 +17,11 @@
package org.jetbrains.kotlin package org.jetbrains.kotlin
import com.intellij.codeInsight.CodeInsightSettings import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.openapi.application.ApplicationManager import org.jdom.Element
import com.intellij.openapi.command.CommandProcessor
import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.JetWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.JetWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
import org.jetbrains.kotlin.idea.testUtils.dumpTextWithErrors
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.InTextDirectivesUtils
@@ -35,8 +35,8 @@ public abstract class AbstractImportsTest : JetLightCodeInsightFixtureTestCase()
protected fun doTest(testPath: String) { protected fun doTest(testPath: String) {
val codeInsightSettings = CodeInsightSettings.getInstance() val codeInsightSettings = CodeInsightSettings.getInstance()
val codeStyleSettings = JetCodeStyleSettings.getInstance(getProject()) val codeStyleSettings = JetCodeStyleSettings.getInstance(getProject())
val optimizeImportsBefore = codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY val codeStyleSettingsSaved = codeStyleSettings.clone() as JetCodeStyleSettings
val nameCountToUseStarBefore = codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT val optimizeImportsSaved = codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY
try { try {
val fixture = myFixture val fixture = myFixture
@@ -54,17 +54,23 @@ public abstract class AbstractImportsTest : JetLightCodeInsightFixtureTestCase()
val file = fixture.getFile() as JetFile val file = fixture.getFile() as JetFile
codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY = InTextDirectivesUtils.getPrefixedBoolean(file.getText(), "// OPTIMIZE_IMPORTS:") ?: false codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY = InTextDirectivesUtils.getPrefixedBoolean(file.getText(), "// OPTIMIZE_IMPORTS:") ?: false
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT = InTextDirectivesUtils.getPrefixedInt(file.getText(), "// NAME_COUNT_TO_USE_STAR_IMPORT:") ?: nameCountToUseStarImportDefault codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT = InTextDirectivesUtils.getPrefixedInt(file.getText(), "// NAME_COUNT_TO_USE_STAR_IMPORT:") ?: nameCountToUseStarImportDefault
codeStyleSettings.IMPORT_PACKAGES = InTextDirectivesUtils.getPrefixedBoolean(file.getText(), "// IMPORT_PACKAGES:") ?: true
codeStyleSettings.IMPORT_NESTED_CLASSES = InTextDirectivesUtils.getPrefixedBoolean(file.getText(), "// IMPORT_NESTED_CLASSES:") ?: false
getProject().executeWriteCommand("") { getProject().executeWriteCommand("") {
doTest(file) doTest(file)
} }
fixture.checkResultByFile(testPath + ".after") JetTestUtils.assertEqualsToFile(File(testPath + ".after"), myFixture.getFile().getText())
} }
finally { finally {
codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY = optimizeImportsBefore codeInsightSettings.OPTIMIZE_IMPORTS_ON_THE_FLY = optimizeImportsSaved
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT = nameCountToUseStarBefore
val root = Element("fake")
codeStyleSettingsSaved.writeExternal(root, codeStyleSettings)
codeStyleSettings.readExternal(root)
} }
} }
@@ -143,6 +143,12 @@ public class AddImportTestGenerated extends AbstractAddImportTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("DoNotImportNestedClass.kt")
public void testDoNotImportNestedClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/addImport/DoNotImportNestedClass.kt");
doTest(fileName);
}
@TestMetadata("DropExplicitImports.kt") @TestMetadata("DropExplicitImports.kt")
public void testDropExplicitImports() throws Exception { public void testDropExplicitImports() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/addImport/DropExplicitImports.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/addImport/DropExplicitImports.kt");
@@ -185,6 +191,12 @@ public class AddImportTestGenerated extends AbstractAddImportTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("ImportNestedClass.kt")
public void testImportNestedClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/addImport/ImportNestedClass.kt");
doTest(fileName);
}
@TestMetadata("ImportPackage.kt") @TestMetadata("ImportPackage.kt")
public void testImportPackage() throws Exception { public void testImportPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/addImport/ImportPackage.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/addImport/ImportPackage.kt");