diff --git a/annotations/com/intellij/openapi/vfs/annotations.xml b/annotations/com/intellij/openapi/vfs/annotations.xml
index 9b0910eb5de..1541d73845c 100644
--- a/annotations/com/intellij/openapi/vfs/annotations.xml
+++ b/annotations/com/intellij/openapi/vfs/annotations.xml
@@ -1,9 +1,12 @@
- -
-
-
- -
-
-
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.kt b/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.kt
index b2c5b933dfd..337c900d28b 100644
--- a/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzerFacade.kt
@@ -77,6 +77,7 @@ public trait PlatformAnalysisParameters
public trait ModuleInfo {
public val name: Name
public fun dependencies(): List
+ public fun friends(): Collection = listOf()
public fun dependencyOnBuiltins(): DependencyOnBuiltins = DependenciesOnBuiltins.LAST
//TODO: (module refactoring) provide dependency on builtins after runtime in IDEA
@@ -137,12 +138,24 @@ public trait AnalyzerFacade
+ val descriptor = resolverForProject.descriptorForModule(module)
+ module.friends().forEach {
+ descriptor.addFriend(resolverForProject.descriptorForModule(it as M))
+ }
+ }
+ }
+
+ addFriends()
+
+ resolverForProject.descriptorByModule.values().forEach { it.seal() }
+
fun initializeResolverForProject() {
modules.forEach {
module ->
diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/IdeaModuleInfos.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/IdeaModuleInfos.kt
index aa20d915f25..4a6f51072f1 100644
--- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/IdeaModuleInfos.kt
+++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/IdeaModuleInfos.kt
@@ -86,9 +86,11 @@ public data class ModuleProductionSourceInfo(val module: Module) : IdeaModuleInf
override fun contentScope() = module.getModuleScope(false)
override fun dependencies() = ideaModelDependencies(module, productionOnly = true)
+
+ override fun friends() = listOf(module.testSourceInfo())
}
-//TODO: (module refactoring) do not create ModuleTestSourceInfo when there are not test roots for module
+//TODO: (module refactoring) do not create ModuleTestSourceInfo when there are no test roots for module
public data class ModuleTestSourceInfo(val module: Module) : IdeaModuleInfo() {
override val name = Name.special("")
diff --git a/idea/testData/multiModuleHighlighting/testRoot/m1/m1.kt b/idea/testData/multiModuleHighlighting/testRoot/m1/m1.kt
new file mode 100644
index 00000000000..fc84bb123c8
--- /dev/null
+++ b/idea/testData/multiModuleHighlighting/testRoot/m1/m1.kt
@@ -0,0 +1,36 @@
+package shared
+
+import shared.test.*
+
+private fun privateInM1() {
+}
+fun internalInM1() {
+}
+public fun publicInM1() {
+}
+
+fun access() {
+ privateInM1()
+ internalInM1()
+ publicInM1()
+
+ privateInM1Test()
+ internalInM1Test()
+ publicInM1Test()
+
+ privateInM2()
+ internalInM2()
+ publicInM2()
+
+ privateInM2Test()
+ internalInM2Test()
+ publicInM2Test()
+
+ privateInM3()
+ internalInM3()
+ publicInM3()
+
+ privateInM3Test()
+ internalInM3Test()
+ publicInM3Test()
+}
\ No newline at end of file
diff --git a/idea/testData/multiModuleHighlighting/testRoot/m1Test/m1Test.kt b/idea/testData/multiModuleHighlighting/testRoot/m1Test/m1Test.kt
new file mode 100644
index 00000000000..a66b3f63bc3
--- /dev/null
+++ b/idea/testData/multiModuleHighlighting/testRoot/m1Test/m1Test.kt
@@ -0,0 +1,36 @@
+package shared.test
+
+import shared.*
+
+private fun privateInM1Test() {
+}
+fun internalInM1Test() {
+}
+public fun publicInM1Test() {
+}
+
+fun access() {
+ privateInM1()
+ internalInM1()
+ publicInM1()
+
+ privateInM1Test()
+ internalInM1Test()
+ publicInM1Test()
+
+ privateInM2()
+ internalInM2()
+ publicInM2()
+
+ privateInM2Test()
+ internalInM2Test()
+ publicInM2Test()
+
+ privateInM3()
+ internalInM3()
+ publicInM3()
+
+ privateInM3Test()
+ internalInM3Test()
+ publicInM3Test()
+}
\ No newline at end of file
diff --git a/idea/testData/multiModuleHighlighting/testRoot/m2/m2.kt b/idea/testData/multiModuleHighlighting/testRoot/m2/m2.kt
new file mode 100644
index 00000000000..874daf6137a
--- /dev/null
+++ b/idea/testData/multiModuleHighlighting/testRoot/m2/m2.kt
@@ -0,0 +1,36 @@
+package shared
+
+import shared.test.*
+
+private fun privateInM2() {
+}
+fun internalInM2() {
+}
+public fun publicInM2() {
+}
+
+fun access() {
+ privateInM1()
+ internalInM1()
+ publicInM1()
+
+ privateInM1Test()
+ internalInM1Test()
+ publicInM1Test()
+
+ privateInM2()
+ internalInM2()
+ publicInM2()
+
+ privateInM2Test()
+ internalInM2Test()
+ publicInM2Test()
+
+ privateInM3()
+ internalInM3()
+ publicInM3()
+
+ privateInM3Test()
+ internalInM3Test()
+ publicInM3Test()
+}
\ No newline at end of file
diff --git a/idea/testData/multiModuleHighlighting/testRoot/m2Test/m2Test.kt b/idea/testData/multiModuleHighlighting/testRoot/m2Test/m2Test.kt
new file mode 100644
index 00000000000..03f292b8af7
--- /dev/null
+++ b/idea/testData/multiModuleHighlighting/testRoot/m2Test/m2Test.kt
@@ -0,0 +1,36 @@
+package shared.test
+
+import shared.*
+
+private fun privateInM2Test() {
+}
+fun internalInM2Test() {
+}
+public fun publicInM2Test() {
+}
+
+fun access() {
+ privateInM1()
+ internalInM1()
+ publicInM1()
+
+ privateInM1Test()
+ internalInM1Test()
+ publicInM1Test()
+
+ privateInM2()
+ internalInM2()
+ publicInM2()
+
+ privateInM2Test()
+ internalInM2Test()
+ publicInM2Test()
+
+ privateInM3()
+ internalInM3()
+ publicInM3()
+
+ privateInM3Test()
+ internalInM3Test()
+ publicInM3Test()
+}
\ No newline at end of file
diff --git a/idea/testData/multiModuleHighlighting/testRoot/m3/m3.kt b/idea/testData/multiModuleHighlighting/testRoot/m3/m3.kt
new file mode 100644
index 00000000000..02ca0c0f838
--- /dev/null
+++ b/idea/testData/multiModuleHighlighting/testRoot/m3/m3.kt
@@ -0,0 +1,36 @@
+package shared
+
+import shared.test.*
+
+private fun privateInM3() {
+}
+fun internalInM3() {
+}
+public fun publicInM3() {
+}
+
+fun access() {
+ privateInM1()
+ internalInM1()
+ publicInM1()
+
+ privateInM1Test()
+ internalInM1Test()
+ publicInM1Test()
+
+ privateInM2()
+ internalInM2()
+ publicInM2()
+
+ privateInM2Test()
+ internalInM2Test()
+ publicInM2Test()
+
+ privateInM3()
+ internalInM3()
+ publicInM3()
+
+ privateInM3Test()
+ internalInM3Test()
+ publicInM3Test()
+}
\ No newline at end of file
diff --git a/idea/testData/multiModuleHighlighting/testRoot/m3Test/m3Test.kt b/idea/testData/multiModuleHighlighting/testRoot/m3Test/m3Test.kt
new file mode 100644
index 00000000000..50b6f1ef0a7
--- /dev/null
+++ b/idea/testData/multiModuleHighlighting/testRoot/m3Test/m3Test.kt
@@ -0,0 +1,36 @@
+package shared.test
+
+import shared.*
+
+private fun privateInM3Test() {
+}
+fun internalInM3Test() {
+}
+public fun publicInM3Test() {
+}
+
+fun access() {
+ privateInM1()
+ internalInM1()
+ publicInM1()
+
+ privateInM1Test()
+ internalInM1Test()
+ publicInM1Test()
+
+ privateInM2()
+ internalInM2()
+ publicInM2()
+
+ privateInM2Test()
+ internalInM2Test()
+ publicInM2Test()
+
+ privateInM3()
+ internalInM3()
+ publicInM3()
+
+ privateInM3Test()
+ internalInM3Test()
+ publicInM3Test()
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/jet/plugin/caches/resolve/MultiModuleHighlightingTest.kt b/idea/tests/org/jetbrains/jet/plugin/caches/resolve/MultiModuleHighlightingTest.kt
index f219902df8d..0ce456c31d3 100644
--- a/idea/tests/org/jetbrains/jet/plugin/caches/resolve/MultiModuleHighlightingTest.kt
+++ b/idea/tests/org/jetbrains/jet/plugin/caches/resolve/MultiModuleHighlightingTest.kt
@@ -22,6 +22,13 @@ import com.intellij.openapi.roots.ModuleRootModificationUtil
import org.jetbrains.jet.plugin.project.PluginJetFilesProvider
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase
import com.intellij.openapi.module.Module
+import com.intellij.openapi.vfs.LocalFileSystem
+import com.intellij.openapi.command.WriteCommandAction
+import com.intellij.testFramework.PsiTestUtil
+import java.io.File
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.openapi.roots.DependencyScope
+import org.junit.Assert
class MultiModuleHighlightingTest : DaemonAnalyzerTestCase() {
@@ -55,16 +62,54 @@ class MultiModuleHighlightingTest : DaemonAnalyzerTestCase() {
checkHighlightingInAllFiles()
}
+ fun testTestRoot() {
+ val module1 = module("m1", hasTestRoot = true)
+ val module2 = module("m2", hasTestRoot = true)
+ val module3 = module("m3", hasTestRoot = true)
+
+ module3.addDependency(module1, dependencyScope = DependencyScope.TEST)
+ module3.addDependency(module2, dependencyScope = DependencyScope.TEST)
+ module2.addDependency(module1, dependencyScope = DependencyScope.COMPILE)
+
+ checkHighlightingInAllFiles()
+ }
+
private fun checkHighlightingInAllFiles() {
+ var atLeastOneFile = false
PluginJetFilesProvider.allFilesInProject(myProject!!).forEach { file ->
+ atLeastOneFile = true
configureByExistingFile(file.getVirtualFile()!!)
checkHighlighting(myEditor, true, false)
}
+ Assert.assertTrue(atLeastOneFile)
}
- private fun module(name: String): Module {
- return createModuleFromTestData(TEST_DATA_PATH + "${getTestName(true)}/$name", "$name", StdModuleTypes.JAVA, true)!!
+ private fun module(name: String, hasTestRoot: Boolean = false): Module {
+ val srcDir = TEST_DATA_PATH + "${getTestName(true)}/$name"
+ val moduleWithSrcRootSet = createModuleFromTestData(srcDir, "$name", StdModuleTypes.JAVA, true)!!
+ if (hasTestRoot) {
+ setTestRoot(moduleWithSrcRootSet, name)
+ }
+ return moduleWithSrcRootSet
}
- private fun Module.addDependency(other: Module) = ModuleRootModificationUtil.addDependency(this, other)
+ private fun setTestRoot(module: Module, name: String) {
+ val testDir = TEST_DATA_PATH + "${getTestName(true)}/${name}Test"
+ val testRootDirInTestData = File(testDir)
+ val testRootDir = createTempDirectory()!!
+ FileUtil.copyDir(testRootDirInTestData, testRootDir)
+ val testRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(testRootDir)!!
+ object : WriteCommandAction.Simple(getProject()) {
+ override fun run() {
+ testRoot.refresh(false, true)
+ }
+ }.execute().throwException()
+ PsiTestUtil.addSourceRoot(module, testRoot, true)
+ }
+
+ private fun Module.addDependency(
+ other: Module,
+ dependencyScope: DependencyScope = DependencyScope.COMPILE,
+ exported: Boolean = false
+ ) = ModuleRootModificationUtil.addDependency(this, other, dependencyScope, exported)
}
\ No newline at end of file