fix access from tests to internal elements in production code in case of circular dependency

Original commit: 5b59fc74bc
This commit is contained in:
Michael Nedzelsky
2015-11-09 15:42:16 +03:00
parent 934a969c2f
commit ba12afbbb9
24 changed files with 258 additions and 7 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.incremental.ProjectBuildException;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.kotlin.config.IncrementalCompilation;
import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder;
@@ -61,6 +62,11 @@ public class KotlinBuilderModuleScriptGenerator {
ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
for (ModuleBuildTarget target : chunk.getTargets()) {
File outputDir = getOutputDirSafe(target);
List<File> friendDirs = new ArrayList<File>();
File friendDir = getFriendDirSafe(target);
if (friendDir != null) {
friendDirs.add(friendDir);
}
List<File> moduleSources = new ArrayList<File>(
IncrementalCompilation.isEnabled()
@@ -85,7 +91,8 @@ public class KotlinBuilderModuleScriptGenerator {
findClassPathRoots(target),
(JavaModuleBuildTargetType) targetType,
// this excludes the output directories from the class path, to be removed for true incremental compilation
outputDirs
outputDirs,
friendDirs
);
}
@@ -107,6 +114,17 @@ public class KotlinBuilderModuleScriptGenerator {
return outputDir;
}
@Nullable
public static File getFriendDirSafe(@NotNull ModuleBuildTarget target) throws ProjectBuildException {
if (!target.isTests()) return null;
File outputDirForProduction = JpsJavaExtensionService.getInstance().getOutputDirectory(target.getModule(), false);
if (outputDirForProduction == null) {
throw new ProjectBuildException("No output production directory found for " + target);
}
return outputDirForProduction;
}
@NotNull
private static Collection<File> findClassPathRoots(@NotNull ModuleBuildTarget target) {
return ContainerUtil.filter(getAllDependencies(target).classes().getRoots(), new Condition<File>() {
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.utils.Printer;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -47,7 +48,8 @@ public class KotlinModuleXmlBuilder {
List<JvmSourceRoot> javaSourceRoots,
Collection<File> classpathRoots,
JavaModuleBuildTargetType targetType,
Set<File> directoriesToFilterOut
Set<File> directoriesToFilterOut,
@NotNull List<File> friendDirs
) {
assert !done : "Already done";
@@ -65,6 +67,10 @@ public class KotlinModuleXmlBuilder {
);
p.pushIndent();
for (File friendDir : friendDirs) {
p.println("<", FRIEND_DIR, " ", PATH, "=\"", getEscapedPath(friendDir), "\"/>");
}
for (File sourceFile : sourceFiles) {
p.println("<", SOURCES, " ", PATH, "=\"", getEscapedPath(sourceFile), "\"/>");
}
@@ -503,6 +503,21 @@ public class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
checkWhen(touch("module2/src/b.kt"), null, packageClasses("module2", "module2/src/b.kt", "test.TestPackage"))
}
public fun testCircularDependenciesSamePackageWithTests() {
initProject()
val result = makeAll()
result.assertSuccessful()
// Check that outputs are located properly
val facadeWithA = findFileInOutputDir(findModule("module1"), "test/AKt.class")
val facadeWithB = findFileInOutputDir(findModule("module2"), "test/BKt.class")
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithA), "<clinit>", "a", "funA", "getA")
UsefulTestCase.assertSameElements(getMethodsOfClass(facadeWithB), "<clinit>", "b", "funB", "getB", "setB")
checkWhen(touch("module1/src/a.kt"), null, packageClasses("module1", "module1/src/a.kt", "test.TestPackage"))
checkWhen(touch("module2/src/b.kt"), null, packageClasses("module2", "module2/src/b.kt", "test.TestPackage"))
}
public fun testInternalFromAnotherModule() {
initProject()
val result = makeAll()
@@ -517,6 +532,13 @@ public class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
result.checkErrors()
}
public fun testCircularDependenciesWrongInternalFromTests() {
initProject()
val result = makeAll()
result.assertFailed()
result.checkErrors()
}
public fun testCircularDependencyWithReferenceToOldVersionLib() {
initProject()
@@ -47,7 +47,8 @@ public class ClasspathOrderTest : TestCaseWithTmpdir() {
listOf(JvmSourceRoot(sourceDir)),
listOf(PathUtil.getKotlinPathsForDistDirectory().getRuntimePath()),
JavaModuleBuildTargetType.PRODUCTION,
setOf()
setOf(),
emptyList()
).asText().toString()
val xml = File(tmpdir, "module.xml")
@@ -34,7 +34,8 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Collections.singletonList(new JvmSourceRoot(new File("java"), null)),
Arrays.asList(new File("cp1"), new File("cp2")),
JavaModuleBuildTargetType.PRODUCTION,
Collections.<File>emptySet()
Collections.<File>emptySet(),
Collections.<File>emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/basic.xml"), actual);
}
@@ -47,7 +48,8 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Collections.<JvmSourceRoot>emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
JavaModuleBuildTargetType.PRODUCTION,
Collections.singleton(new File("cp1"))
Collections.singleton(new File("cp1")),
Collections.<File>emptyList()
).asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/filtered.xml"), actual);
}
@@ -61,7 +63,8 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Collections.<JvmSourceRoot>emptyList(),
Arrays.asList(new File("cp1"), new File("cp2")),
JavaModuleBuildTargetType.PRODUCTION,
Collections.singleton(new File("cp1"))
Collections.singleton(new File("cp1")),
Collections.<File>emptyList()
);
builder.addModule(
"name2",
@@ -70,7 +73,8 @@ public class KotlinModuleXmlGeneratorTest extends TestCase {
Collections.<JvmSourceRoot>emptyList(),
Arrays.asList(new File("cp12"), new File("cp22")),
JavaModuleBuildTargetType.TEST,
Collections.singleton(new File("cp12"))
Collections.singleton(new File("cp12")),
Collections.<File>emptyList()
);
String actual = builder.asText().toString();
KotlinTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/multiple.xml"), actual);
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
<component name="CopyrightManager" default="">
<module2copyright />
</component>
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/module1/module1.iml" filepath="$PROJECT_DIR$/module1/module1.iml" />
<module fileurl="file://$PROJECT_DIR$/module2/module2.iml" filepath="$PROJECT_DIR$/module2/module2.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA_JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="module2" />
<orderEntry type="library" name="KotlinRuntime" level="project" />
</component>
</module>
@@ -0,0 +1,9 @@
package test
fun a() {
}
internal fun funA() {}
val a = ""
@@ -0,0 +1,3 @@
package test
internal fun testFunA() {}
@@ -0,0 +1,6 @@
package test
fun foo() {
funA()
testFunA()
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="module1" />
<orderEntry type="library" name="KotlinRuntime" level="project" />
</component>
</module>
@@ -0,0 +1,9 @@
package test
fun b() {
}
internal fun funB() {}
var b = b()
@@ -0,0 +1,3 @@
package test
internal fun testFunB() {}
@@ -0,0 +1,6 @@
package test
fun bar() {
funB()
testFunB()
}
@@ -0,0 +1,4 @@
Cannot access 'funA': it is 'internal' in 'test' at line 4, column 5
Cannot access 'funB': it is 'internal' in 'test' at line 4, column 5
Cannot access 'testFunA': it is 'internal' in 'test' at line 5, column 5
Cannot access 'testFunB': it is 'internal' in 'test' at line 5, column 5
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
<component name="CopyrightManager" default="">
<module2copyright />
</component>
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/module1/module1.iml" filepath="$PROJECT_DIR$/module1/module1.iml" />
<module fileurl="file://$PROJECT_DIR$/module2/module2.iml" filepath="$PROJECT_DIR$/module2/module2.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA_JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="module2" />
<orderEntry type="library" name="KotlinRuntime" level="project" />
</component>
</module>
@@ -0,0 +1,9 @@
package test
fun a() {
}
internal fun funA() {}
val a = ""
@@ -0,0 +1,3 @@
package test
internal fun testFunA() {}
@@ -0,0 +1,6 @@
package test
fun foo() {
funB()
testFunB()
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="module1" />
<orderEntry type="library" name="KotlinRuntime" level="project" />
</component>
</module>
@@ -0,0 +1,9 @@
package test
fun b() {
}
internal fun funB() {}
var b = b()
@@ -0,0 +1,3 @@
package test
internal fun testFunB() {}
@@ -0,0 +1,6 @@
package test
fun bar() {
funA()
testFunA()
}