Skip to content

Commit

Permalink
Use old resolve inside cfg-disabled file shadowed by cfg-enabled file
Browse files Browse the repository at this point in the history
  • Loading branch information
dima74 committed Sep 16, 2020
1 parent 42f42ef commit 8540991
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/main/kotlin/org/rust/lang/core/resolve2/FacadeBuild.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,23 @@ import java.util.concurrent.atomic.AtomicInteger
val defMap = buildDefMapContainingExplicitItems(context, dependenciesDefMaps) ?: return null
DefCollector(project, defMap, context).collect()
project.defMapService.afterDefMapBuilt(defMap)
defMap.afterBuilt()
return defMap
}

private fun CrateDefMap.afterBuilt() {
fun ModData.visitDescendants(visitor: (ModData) -> Unit) {
visitor(this)
for (childMod in childModules.values) {
childMod.visitDescendants(visitor)
}
}

root.visitDescendants {
it.isShadowedByOtherFile = false
}
}

fun DefMapService.getOrUpdateIfNeeded(crate: Crate): CrateDefMap? {
check(project.isNewResolveEnabled)
val holder = getDefMapHolder(crate.id ?: return null)
Expand Down
15 changes: 14 additions & 1 deletion src/main/kotlin/org/rust/lang/core/resolve2/FacadeResolve.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,30 @@ import org.rust.openapiext.toPsiFile
val Project.isNewResolveEnabled: Boolean
get() = rustSettings.newResolveEnabled || true

fun shouldUseNewResolveIn(scope: RsMod) =
fun shouldUseNewResolveIn(scope: RsMod): Boolean =
scope.project.isNewResolveEnabled
&& scope.containingCrate is CargoBasedCrate
&& scope.modName != TMP_MOD_NAME
&& !scope.isModInsideItem
&& scope.containingCrate != null
&& !scope.isShadowedByOtherMod()

private val RsMod.isModInsideItem: Boolean
// todo `mod foo { mod inner; }` - так можно?)
get() = this is RsModItem && context !is RsMod

/** "shadowed by other mod" means that [ModData] is not accessible from [CrateDefMap.root] through [ModData.childModules] */
private fun RsMod.isShadowedByOtherMod(): Boolean {
// todo performance: `getDefMapAndModData` is called twice
val (_, modData) = project.getDefMapAndModData(this) ?: return false
val isShadowedByOtherFile = modData.isShadowedByOtherFile

val isDeeplyEnabledByCfg = (containingFile as RsFile).isDeeplyEnabledByCfg && isEnabledByCfg
val isShadowedByOtherInlineMod = isDeeplyEnabledByCfg != modData.isDeeplyEnabledByCfg

return isShadowedByOtherFile || isShadowedByOtherInlineMod
}

fun processItemDeclarations2(
scope: RsMod,
ns: Set<Namespace>,
Expand Down
8 changes: 8 additions & 0 deletions src/main/kotlin/org/rust/lang/core/resolve2/resolve.kt
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ class ModData(
/** Traits imported via `use Trait as _;` */
val unnamedTraitImports: MutableMap<ModPath, Visibility> = hashMapOf()

/**
* Make sense only for files ([isRsFile] == true).
* Value `false` means that `this` is not accessible from [CrateDefMap.root] through [ModData.childModules],
* but can be accessible using [CrateDefMap.fileInfos].
* It could happen when two mod declarations with same path has different cfg-attributes.
*/
var isShadowedByOtherFile: Boolean = true

operator fun get(name: String): PerNs = visibleItems.getOrDefault(name, PerNs.Empty)

fun getVisibleItems(filterVisibility: (Visibility) -> Boolean): List<Pair<String, PerNs>> {
Expand Down
36 changes: 36 additions & 0 deletions src/test/kotlin/org/rust/lang/core/resolve/RsCfgAttrResolveTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,42 @@ class RsCfgAttrResolveTest : RsResolveTestBase() {
}
""")

@MockEdition(CargoWorkspace.Edition.EDITION_2018)
@MockAdditionalCfgOptions("intellij_rust")
fun `test resolve inside inline mod with cfg`() = checkByCode("""
#[cfg(not(intellij_rust))]
mod foo {
fn test() {
bar();
} //^
fn bar() {}
//X
}
#[cfg(intellij_rust)]
mod foo {
fn bar() {}
}
""")

@MockEdition(CargoWorkspace.Edition.EDITION_2018)
@MockAdditionalCfgOptions("intellij_rust")
fun `test resolve inside non-inline mod with cfg`() = stubOnlyResolve("""
//- main.rs
#[cfg(intellij_rust)]
mod foo;
#[cfg(not(intellij_rust))]
#[path="foo_disabled.rs"]
mod foo;
//- foo.rs
fn bar() {}
//- foo_disabled.rs
fn test() {
bar();
} //^ foo_disabled.rs
fn bar() {}
//X
""")

@MockAdditionalCfgOptions("intellij_rust")
fun `test use item with cfg`() = checkByCode("""
mod my {
Expand Down

0 comments on commit 8540991

Please sign in to comment.