KTIJ-27841 [AA] Do not import and shorten class constructor if it will alter other references in the file

N.B. This implementation does not 100% prevent conflicts or resolve
alterations when shortening functions.
To guarantee that,
we would need to carefully consider all the references in the file,
and to check whether they have changed their resolve in the presence
of a new import.
This is not trivial and will be approached separately under a different
task.

^KTIJ-27841 Fixed
This commit is contained in:
Roman Golyshev
2024-01-11 12:51:45 +01:00
committed by teamcity
parent 1e2f612cbc
commit 646cdb56e5
3 changed files with 28 additions and 6 deletions
@@ -595,7 +595,11 @@ private class ElementsToShortenCollector(
findClassifierQualifierToShorten(wholeClassQualifier, wholeQualifierElement)?.let(::addElementToShorten)
}
private val FirClassifierSymbol<*>.classIdIfExists: ClassId? get() = (this as? FirClassLikeSymbol<*>)?.classId
private val FirClassifierSymbol<*>.classIdIfExists: ClassId?
get() = (this as? FirClassLikeSymbol<*>)?.classId
private val FirConstructorSymbol.classIdIfExists: ClassId?
get() = this.containingClassLookupTag()?.classId
/**
* Returns true if the class symbol has a type parameter that is supposed to be provided for its parent class.
@@ -929,6 +933,22 @@ private class ElementsToShortenCollector(
return importAffectsUsagesOfClassesWithSameName(classToImport, file, importAllInParent)
}
/**
* Same as above, but for more general callable symbols.
*
* Currently only checks constructor calls, assuming `true` for everything else.
*/
private fun importBreaksExistingReferences(callableToImport: FirCallableSymbol<*>, file: KtFile, importAllInParent: Boolean): Boolean {
if (callableToImport is FirConstructorSymbol) {
val classToImport = callableToImport.classIdIfExists
if (classToImport != null) {
return importAffectsUsagesOfClassesWithSameName(classToImport, file, importAllInParent)
}
}
return false
}
private fun importedClassifierOverwritesAvailableClassifier(
availableClassifier: AvailableSymbol<FirClassifierSymbol<*>>,
importAllInParent: Boolean
@@ -1221,15 +1241,21 @@ private class ElementsToShortenCollector(
when {
matchedCallables.isEmpty() -> {
if (nameToImport == null || option == ShortenStrategy.SHORTEN_IF_ALREADY_IMPORTED) return null
val importAllInParent = option == ShortenStrategy.SHORTEN_AND_STAR_IMPORT
if (importBreaksExistingReferences(calledSymbol, qualifiedCallExpression.containingKtFile, importAllInParent)) return null
createElementToShorten(
qualifiedCallExpression,
nameToImport,
importAllInParent = option == ShortenStrategy.SHORTEN_AND_STAR_IMPORT
importAllInParent,
)
}
// Respect caller's request to star import this symbol.
matchedCallables.any { it.importKind == ImportKind.EXPLICIT } && option == ShortenStrategy.SHORTEN_AND_STAR_IMPORT ->
createElementToShorten(qualifiedCallExpression, nameToImport, importAllInParent = true)
else -> createElementToShorten(qualifiedCallExpression)
}
}
@@ -1,8 +1,6 @@
Before shortening: dependency.MyFoo()
with default settings:
[qualifier] dependency.MyFoo()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
[qualifier] dependency.MyFoo()
with SHORTEN_AND_STAR_IMPORT:
@@ -1,8 +1,6 @@
Before shortening: dependency.MyFoo()
with default settings:
[qualifier] dependency.MyFoo()
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
[qualifier] dependency.MyFoo()
with SHORTEN_AND_STAR_IMPORT: