fix access from tests to internal elements in production code in case of circular dependency
Original commit: 5b59fc74bc
This commit is contained in:
+19
-1
@@ -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);
|
||||
|
||||
+32
@@ -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>
|
||||
|
||||
+15
@@ -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>
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
fun a() {
|
||||
|
||||
}
|
||||
|
||||
internal fun funA() {}
|
||||
|
||||
val a = ""
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
internal fun testFunA() {}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
funA()
|
||||
testFunA()
|
||||
}
|
||||
+15
@@ -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>
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
fun b() {
|
||||
|
||||
}
|
||||
|
||||
internal fun funB() {}
|
||||
|
||||
var b = b()
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
internal fun testFunB() {}
|
||||
+6
@@ -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
|
||||
+32
@@ -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>
|
||||
|
||||
+15
@@ -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>
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
fun a() {
|
||||
|
||||
}
|
||||
|
||||
internal fun funA() {}
|
||||
|
||||
val a = ""
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
internal fun testFunA() {}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
fun foo() {
|
||||
funB()
|
||||
testFunB()
|
||||
}
|
||||
+15
@@ -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>
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test
|
||||
|
||||
fun b() {
|
||||
|
||||
}
|
||||
|
||||
internal fun funB() {}
|
||||
|
||||
var b = b()
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
internal fun testFunB() {}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
fun bar() {
|
||||
funA()
|
||||
testFunA()
|
||||
}
|
||||
Reference in New Issue
Block a user