[Analysis API] Add source shadowing for resolve extensions.
KtResolveExtensions are designed to handle IDE analysis use cases where source might not be available at analysis time, because that source is generated by an external source generator, such as an annotation processor or resource compiler. The sources generated by those external generators can appear in the analysis scope, and cause issues with source clash - resolution may find the virtual source from the KtResolveExtension, the on-disk generated source from the external generator, or both. This can cause issues, because that on-disk generated source may be stale, and may not have symbols that will exist the next time the generator is run (or, conversely, may have symbols that will disappear on the next build). To solve this, add a `getShadowedScope(): GlobalSearchScope` to `KtResolveExtension`. Any files in the module that are included in that scope will be hidden from resolution, allowing the resolve extension to cleanly replace those files. ^KT-58834 fixed
This commit is contained in:
committed by
Ilya Kirillov
parent
7c87eb098d
commit
f590e88bdd
+14
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.api.resolve.extensions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
/**
|
||||
@@ -53,4 +54,17 @@ public abstract class KtResolveExtension {
|
||||
* @see KtResolveExtension
|
||||
*/
|
||||
public abstract fun getContainedPackages(): Set<FqName>
|
||||
|
||||
/**
|
||||
* Returns the scope of files that should be shadowed by the files provided by [getKtFiles].
|
||||
*
|
||||
* Any files in the module that are included in this scope will be removed from analysis results. This allows the files provided by
|
||||
* [getKtFiles] to cleanly replace those files from the module.
|
||||
*
|
||||
* If this resolve extension is being used to generate declarations that would normally be provided by sources generated by an external
|
||||
* build task, such as a resource compiler or annotation processor, the resolve extension should provide a scope here that covers those
|
||||
* externally generated sources. This will prevent collisions between the definitions provided by [getKtFiles] and those provided by the
|
||||
* (potentially stale) externally generated sources.
|
||||
*/
|
||||
public open fun getShadowedScope(): GlobalSearchScope = GlobalSearchScope.EMPTY_SCOPE
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// UNRESOLVED_REFERENCE
|
||||
|
||||
// MODULE: extendedModule
|
||||
// FILE: declarations.hidden.kt
|
||||
package foo
|
||||
|
||||
fun bar() = "baz"
|
||||
|
||||
// MODULE: dependency2
|
||||
|
||||
// MODULE: main(extendedModule, dependency2)()()
|
||||
// FILE: main.kt
|
||||
fun main() {
|
||||
val x = foo.<caret>bar()
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// UNRESOLVED_REFERENCE
|
||||
|
||||
// MODULE: extendedModule
|
||||
// FILE: TestClass.hidden.java
|
||||
package foo;
|
||||
|
||||
public class TestClass {
|
||||
public TestClass() {}
|
||||
}
|
||||
|
||||
// MODULE: dependency2
|
||||
|
||||
// MODULE: main(extendedModule, dependency2)()()
|
||||
// FILE: main.kt
|
||||
package foo
|
||||
|
||||
fun main() {
|
||||
val x = <caret>TestClass()
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// MODULE: extendedModule
|
||||
// FILE: generated.hidden.kt
|
||||
package generated
|
||||
|
||||
fun String.generatedOverloadedExtensionFunction(): Int = TODO()
|
||||
|
||||
// MODULE: dependency2
|
||||
|
||||
// MODULE: main(extendedModule, dependency2)()()
|
||||
// FILE: main.kt
|
||||
import generated.*
|
||||
|
||||
fun main() {
|
||||
"string".generatedOverloadedExtension<caret>Function()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in generated) fun kotlin.Any.generatedOverloadedExtensionFunction(): kotlin.Int
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// UNRESOLVED_REFERENCE
|
||||
|
||||
// FILE: declarations.hidden.kt
|
||||
package foo
|
||||
|
||||
fun bar() = "baz"
|
||||
|
||||
// FILE: main.kt
|
||||
fun main() {
|
||||
val x = foo.<caret>bar()
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// UNRESOLVED_REFERENCE
|
||||
|
||||
// FILE: TestClass.hidden.java
|
||||
package foo;
|
||||
|
||||
public class TestClass {
|
||||
public TestClass() {}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
package foo
|
||||
|
||||
fun main() {
|
||||
val x = <caret>TestClass()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// FILE: generated.hidden.kt
|
||||
package generated
|
||||
|
||||
fun String.generatedOverloadedExtensionFunction(): Int = TODO()
|
||||
|
||||
// FILE: main.kt
|
||||
import generated.*
|
||||
|
||||
fun main() {
|
||||
"string".generatedOverloadedExtension<caret>Function()
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in generated) fun kotlin.Any.generatedOverloadedExtensionFunction(): kotlin.Int
|
||||
Reference in New Issue
Block a user