J2K ImportPath: kotlinify

This commit is contained in:
Pavel V. Talanov
2017-02-13 13:16:11 +03:00
parent 50d0f5bde6
commit babb3b557d
16 changed files with 45 additions and 77 deletions
@@ -28,8 +28,8 @@ object JvmPlatform : TargetPlatform("JVM") {
override fun getDefaultImports(languageVersionSettings: LanguageVersionSettings): List<ImportPath> = ArrayList<ImportPath>().apply {
addAll(Default.getDefaultImports(languageVersionSettings))
add(ImportPath("java.lang.*"))
add(ImportPath("kotlin.jvm.*"))
add(ImportPath.fromString("java.lang.*"))
add(ImportPath.fromString("kotlin.jvm.*"))
fun addAllClassifiersFromScope(scope: MemberScope) {
for (descriptor in scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER)) {
@@ -384,7 +384,7 @@ class KtPsiFactory(private val project: Project) {
}
fun createImportDirective(importPath: ImportPath): KtImportDirective {
if (importPath.fqnPart().isRoot) {
if (importPath.fqName.isRoot) {
throw IllegalArgumentException("import path must not be empty")
}
@@ -20,29 +20,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.renderer.*
class ImportPath {
private val fqName: FqName
val alias: Name?
val isAllUnder: Boolean
@JvmOverloads constructor(fqName: FqName, isAllUnder: Boolean, alias: Name? = null) {
this.fqName = fqName
this.isAllUnder = isAllUnder
this.alias = alias
}
constructor(pathStr: String) {
if (pathStr.endsWith(".*")) {
this.isAllUnder = true
this.fqName = FqName(pathStr.substring(0, pathStr.length - 2))
}
else {
this.isAllUnder = false
this.fqName = FqName(pathStr)
}
alias = null
}
data class ImportPath @JvmOverloads constructor(val fqName: FqName, val isAllUnder: Boolean, val alias: Name? = null) {
val pathStr: String
get() = fqName.toUnsafe().render() + if (isAllUnder) ".*" else ""
@@ -51,10 +29,6 @@ class ImportPath {
return pathStr + if (alias != null) " as " + alias.asString() else ""
}
fun fqnPart(): FqName {
return fqName
}
fun hasAlias(): Boolean {
return alias != null
}
@@ -68,23 +42,15 @@ class ImportPath {
return null
}
override fun equals(o: Any?): Boolean {
if (this === o) return true
if (o == null || javaClass != o.javaClass) return false
companion object {
@JvmStatic fun fromString(pathStr: String): ImportPath {
if (pathStr.endsWith(".*")) {
return ImportPath(FqName(pathStr.substring(0, pathStr.length - 2)), isAllUnder = true)
}
else {
return ImportPath(FqName(pathStr), isAllUnder = false)
val path = o as ImportPath?
if (isAllUnder != path!!.isAllUnder) return false
if (if (alias != null) alias != path.alias else path.alias != null) return false
if (fqName != path.fqName) return false
return true
}
override fun hashCode(): Int {
var result = fqName.hashCode()
result = 31 * result + (alias?.hashCode() ?: 0)
result = 31 * result + if (isAllUnder) 1 else 0
return result
}
}
}
}
@@ -43,16 +43,18 @@ abstract class TargetPlatform(val platformName: String) {
object Default : TargetPlatform("Default") {
override fun getDefaultImports(languageVersionSettings: LanguageVersionSettings): List<ImportPath> = ArrayList<ImportPath>().apply {
add(ImportPath("kotlin.*"))
add(ImportPath("kotlin.annotation.*"))
add(ImportPath("kotlin.collections.*"))
add(ImportPath("kotlin.ranges.*"))
add(ImportPath("kotlin.sequences.*"))
add(ImportPath("kotlin.text.*"))
add(ImportPath("kotlin.io.*"))
listOf(
"kotlin.*",
"kotlin.annotation.*",
"kotlin.collections.*",
"kotlin.ranges.*",
"kotlin.sequences.*",
"kotlin.text.*",
"kotlin.io.*"
).forEach { add(ImportPath.fromString(it)) }
if (languageVersionSettings.supportsFeature(LanguageFeature.DefaultImportOfPackageKotlinComparisons)) {
add(ImportPath("kotlin.comparisons.*"))
add(ImportPath.fromString("kotlin.comparisons.*"))
}
}
@@ -55,7 +55,7 @@ class DefaultImportProvider(
defaultImports
.filter { it.isAllUnder }
.mapNotNull {
it.fqnPart().takeIf { !it.isSubpackageOf(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) }
it.fqName.takeIf { !it.isSubpackageOf(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) }
}
val nonKotlinAliasedTypeFqNames =
builtinTypeAliases
@@ -71,7 +71,7 @@ class FileScopeFactory(
val extraImports = file.originalFile.virtualFile?.let { vFile ->
val scriptExternalDependencies = getScriptExternalDependencies(vFile, file.project)
ktImportsFactory.createImportDirectives(scriptExternalDependencies?.imports?.map(::ImportPath).orEmpty())
ktImportsFactory.createImportDirectives(scriptExternalDependencies?.imports?.map { ImportPath.fromString(it) }.orEmpty())
}
val allImplicitImports = defaultImports concat extraImports
@@ -91,7 +91,7 @@ class OptimizedImportsBuilder(
.mapNotNull { it.importPath }
.filter {
val aliasName = it.alias
aliasName != null && aliasName != it.fqnPart().shortName()
aliasName != null && aliasName != it.fqName.shortName()
}
.mapTo(importRules) { ImportRule.Add(it) }
@@ -48,7 +48,7 @@ private fun KtFile.buildAliasImportMap(): Multimap<String, String> {
val importList = importList ?: return map
for (import in importList.imports) {
val aliasName = import.aliasName ?: continue
val name = import.importPath?.fqnPart()?.shortName()?.asString() ?: continue
val name = import.importPath?.fqName?.shortName()?.asString() ?: continue
map.put(aliasName, name)
}
return map
@@ -45,17 +45,17 @@ fun PsiElement.getKotlinFqName(): FqName? {
fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean {
return when {
skipAliasedImports && importPath.hasAlias() -> false
importPath.isAllUnder && !isRoot -> importPath.fqnPart() == this.parent()
else -> importPath.fqnPart() == this
importPath.isAllUnder && !isRoot -> importPath.fqName == this.parent()
else -> importPath.fqName == this
}
}
fun ImportPath.isImported(alreadyImported: ImportPath): Boolean {
return if (isAllUnder || hasAlias()) this == alreadyImported else fqnPart().isImported(alreadyImported)
return if (isAllUnder || hasAlias()) this == alreadyImported else fqName.isImported(alreadyImported)
}
private fun ImportPath.isImported(imports: Iterable<ImportPath>): Boolean = imports.any { isImported(it) }
fun ImportPath.isImported(imports: Iterable<ImportPath>, excludedFqNames: Iterable<FqName>): Boolean {
return isImported(imports) && (isAllUnder || this.fqnPart() !in excludedFqNames)
return isImported(imports) && (isAllUnder || this.fqName !in excludedFqNames)
}
@@ -391,7 +391,7 @@ fun LookupElement.decorateAsStaticMember(
val psiDocumentManager = PsiDocumentManager.getInstance(context.project)
val file = context.file as KtFile
val addMemberImport = file.importDirectives.any { !it.isAllUnder && it.importPath?.fqnPart()?.parent() == containerFqName }
val addMemberImport = file.importDirectives.any { !it.isAllUnder && it.importPath?.fqName?.parent() == containerFqName }
if (addMemberImport) {
psiDocumentManager.commitAllDocuments()
@@ -34,7 +34,7 @@ class ImportableFqNameClassifier(private val file: KtFile) {
init {
for (import in file.importDirectives) {
val importPath = import.importPath ?: continue
val fqName = importPath.fqnPart()
val fqName = importPath.fqName
if (importPath.isAllUnder) {
allUnderImports.add(fqName)
}
@@ -66,7 +66,7 @@ class KotlinUnusedImportInspection : AbstractKotlinInspection() {
.asSequence()
.mapNotNull { it.importPath }
.filter { !it.isAllUnder && !it.hasAlias() }
.map { it.fqnPart() }
.map { it.fqName }
.toSet()
val fqNames = HashSet<FqName>()
@@ -95,10 +95,10 @@ class KotlinUnusedImportInspection : AbstractKotlinInspection() {
false
}
else if (importPath.isAllUnder) {
importPath.fqnPart() in parentFqNames
importPath.fqName in parentFqNames
}
else {
importPath.fqnPart() in fqNames
importPath.fqName in fqNames
}
if (!isUsed) {
@@ -134,8 +134,8 @@ object ReplaceWithAnnotationAnalyzer {
// this solution doesn't support aliased default imports with a different alias
// TODO: Create import directives from ImportPath, create ImportResolver, create LazyResolverScope, see FileScopeProviderImpl
return listOf(buildExplicitImportsScope(aliasImports.map { it.fqnPart() }, resolutionFacade, module)) +
allUnderImports.map { module.getPackage(it.fqnPart()).memberScope.memberScopeAsImportingScope() }.asReversed()
return listOf(buildExplicitImportsScope(aliasImports.map { it.fqName }, resolutionFacade, module)) +
allUnderImports.map { module.getPackage(it.fqName).memberScope.memberScopeAsImportingScope() }.asReversed()
}
private fun buildExplicitImportsScope(annotation: ReplaceWith, resolutionFacade: ResolutionFacade, module: ModuleDescriptor): ExplicitImportsScope {
@@ -121,7 +121,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
val imports = file.importDirectives
if (imports.any { !it.isAllUnder && it.importPath?.fqnPart() == targetFqName }) {
if (imports.any { !it.isAllUnder && it.importPath?.fqName == targetFqName }) {
return ImportDescriptorResult.FAIL
}
@@ -132,7 +132,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
else -> null
}
if (conflict != null
&& imports.any { !it.isAllUnder && it.importPath?.fqnPart() == conflict.importableFqName && it.importPath?.importedName == name }
&& imports.any { !it.isAllUnder && it.importPath?.fqName == conflict.importableFqName && it.importPath?.importedName == name }
) {
return ImportDescriptorResult.FAIL
}
@@ -187,7 +187,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
val importsFromPackage = imports.count {
val path = it.importPath
path != null && !path.isAllUnder && !path.hasAlias() && path.fqnPart().parent() == containerFqName
path != null && !path.isAllUnder && !path.hasAlias() && path.fqName.parent() == containerFqName
}
val nameCountToUseStar = if (target.containingDeclaration is ClassDescriptor)
codeStyleSettings.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS
@@ -217,7 +217,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
.mapNotNull {
val importPath = it.importPath
if (importPath != null) {
val fqName = importPath.fqnPart()
val fqName = importPath.fqName
getMemberScope(fqName, moduleDescriptor)
}
else {
@@ -300,7 +300,7 @@ class ImportInsertHelperImpl(private val project: Project) : ImportInsertHelper(
private fun dropRedundantExplicitImports(packageFqName: FqName) {
val dropCandidates = file.importDirectives.filter {
!it.isAllUnder && it.aliasName == null && it.importPath?.fqnPart()?.parent() == packageFqName
!it.isAllUnder && it.aliasName == null && it.importPath?.fqName?.parent() == packageFqName
}
val importsToCheck = ArrayList<FqName>()
@@ -163,7 +163,7 @@ private fun renderImportName(fqName: FqName, isOnDemand: Boolean)
// TODO: use the correct LanguageVersionSettings instance here
private val DEFAULT_IMPORTS_SET: Set<FqName> = JvmPlatform.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT)
.filter { it.isAllUnder }
.map { it.fqnPart() }
.map { it.fqName }
.toSet()
private fun isImportedByDefault(c: KtLightClass) = c.qualifiedName?.let { FqName(it).parent() } in DEFAULT_IMPORTS_SET
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.resolve.TargetPlatform
object JsPlatform : TargetPlatform("JS") {
override fun getDefaultImports(languageVersionSettings: LanguageVersionSettings): List<ImportPath> =
Default.getDefaultImports(languageVersionSettings) + ImportPath("kotlin.js.*")
Default.getDefaultImports(languageVersionSettings) + ImportPath.fromString("kotlin.js.*")
override val platformConfigurator: PlatformConfigurator = JsPlatformConfigurator