diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java
index b5f4aeb7381..38753e4e0cf 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java
@@ -18,7 +18,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.psi.PsiFile;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
@@ -269,11 +269,11 @@ public class CodegenUtil {
return ((ImplementationBodyCodegen) classBodyCodegen.getParentCodegen());
}
- static int getPathHashCode(@NotNull PsiFile file) {
+ static int getPathHashCode(@NotNull VirtualFile file) {
// Conversion to system-dependent name seems to be unnecessary, but it's hard to check now:
// it was introduced when fixing KT-2839, which appeared again (KT-3639).
// If you try to remove it, run tests on Windows.
- return FileUtil.toSystemDependentName(file.getVirtualFile().getPath()).hashCode();
+ return FileUtil.toSystemDependentName(file.getPath()).hashCode();
}
@Nullable
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
index 7f21b86a083..3ba136af3e6 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
@@ -186,7 +186,7 @@ public class NamespaceCodegen extends MemberCodegen {
if (!generateSrcClass) return null;
- Type packageFragmentType = getNamespacePartType(getPackageClassFqName(name), file);
+ Type packageFragmentType = getNamespacePartType(getPackageClassFqName(name), file.getVirtualFile());
ClassBuilder builder = state.getFactory().forPackageFragment(packageFragmentType, file);
new NamespacePartCodegen(builder, file, packageFragmentType, packageFragmentContext, state).generate();
@@ -247,7 +247,7 @@ public class NamespaceCodegen extends MemberCodegen {
}
@NotNull
- private static Type getNamespacePartType(@NotNull FqName facadeFqName, @NotNull PsiFile file) {
+ public static Type getNamespacePartType(@NotNull FqName facadeFqName, @NotNull VirtualFile file) {
String fileName = FileUtil.getNameWithoutExtension(PathUtil.getFileName(file.getName()));
// path hashCode to prevent same name / different path collision
@@ -267,6 +267,6 @@ public class NamespaceCodegen extends MemberCodegen {
@NotNull
public static String getNamespacePartInternalName(@NotNull JetFile file) {
FqName packageFqName = JetPsiUtil.getFQName(file);
- return getNamespacePartType(getPackageClassFqName(packageFqName), file).getInternalName();
+ return getNamespacePartType(getPackageClassFqName(packageFqName), file.getVirtualFile()).getInternalName();
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/SamWrapperCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/SamWrapperCodegen.java
index 000f9c000a0..573adaea586 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/SamWrapperCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/SamWrapperCodegen.java
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.MethodVisitor;
@@ -134,11 +135,12 @@ public class SamWrapperCodegen extends ParentCodegenAwareImpl {
private String getWrapperName(@NotNull JetFile containingFile) {
NamespaceDescriptor namespace = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, containingFile);
- assert namespace != null : "couldn't find namespace for file: " + containingFile.getVirtualFile();
+ VirtualFile virtualFile = containingFile.getVirtualFile();
+ assert namespace != null : "couldn't find namespace for file: " + virtualFile;
FqName fqName = DescriptorUtils.getFQName(namespace).toSafe();
String packageInternalName = JvmClassName.byFqNameWithoutInnerClasses(
PackageClassUtils.getPackageClassFqName(fqName)).getInternalName();
return packageInternalName + "$sam$" + samInterface.getName().asString() + "$" +
- Integer.toHexString(CodegenUtil.getPathHashCode(containingFile) * 31 + DescriptorUtils.getFQName(samInterface).hashCode());
+ Integer.toHexString(CodegenUtil.getPathHashCode(virtualFile) * 31 + DescriptorUtils.getFQName(samInterface).hashCode());
}
}
diff --git a/jps-plugin/jps-plugin.iml b/jps-plugin/jps-plugin.iml
index 83efc10247f..c3a06774179 100644
--- a/jps-plugin/jps-plugin.iml
+++ b/jps-plugin/jps-plugin.iml
@@ -14,6 +14,8 @@
+
+
diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java
index 7b72857b7c6..70e32c89e5e 100644
--- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java
+++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java
@@ -34,6 +34,7 @@ import org.jetbrains.jet.compiler.runner.SimpleOutputItem;
import org.jetbrains.jet.jps.JpsKotlinCompilerSettings;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.incremental.*;
@@ -47,10 +48,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.*;
import static org.jetbrains.jet.compiler.runner.KotlinCompilerRunner.runK2JsCompiler;
@@ -165,9 +163,20 @@ public class KotlinBuilder extends ModuleLevelBuilder {
runK2JvmCompiler(commonSettings, k2JvmSettings, messageCollector, environment, moduleFile, outputItemCollector);
}
+ // If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below
+ Map> sourceToTarget = new HashMap>();
+ if (chunk.getTargets().size() > 1) {
+ for (ModuleBuildTarget target : chunk.getTargets()) {
+ for (File file : KotlinSourceFileCollector.getAllKotlinSourceFiles(target)) {
+ sourceToTarget.put(file, target);
+ }
+ }
+ }
+
for (SimpleOutputItem outputItem : outputItemCollector.getOutputs()) {
+ BuildTarget> target = sourceToTarget.get(outputItem.getSourceFiles().iterator().next());
outputConsumer.registerOutputFile(
- representativeTarget,
+ target != null ? target : representativeTarget,
outputItem.getOutputFile(),
paths(outputItem.getSourceFiles()));
}
diff --git a/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTestCase.java b/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTestCase.java
index 1a7320ee144..ac6b16c4fde 100644
--- a/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTestCase.java
+++ b/jps-plugin/test/org/jetbrains/jet/jps/build/KotlinJpsBuildTestCase.java
@@ -18,7 +18,10 @@ package org.jetbrains.jet.jps.build;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.jet.codegen.NamespaceCodegen;
+import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jps.builders.BuildResult;
import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
@@ -26,6 +29,7 @@ import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.util.JpsPathUtil;
import java.io.File;
+import java.io.IOException;
public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
private static final String PROJECT_NAME = "kotlinProject";
@@ -36,6 +40,7 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
super.setUp();
File sourceFilesRoot = new File(TEST_DATA_PATH + getTestName(false));
workDir = copyTestDataToTmpDir(sourceFilesRoot);
+ getOrCreateProjectDir();
}
@Override
@@ -44,6 +49,11 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
super.tearDown();
}
+ @Override
+ protected File doGetProjectDir() throws IOException {
+ return workDir;
+ }
+
private void initProject() {
addJdk(JDK_NAME);
loadProject(workDir.getAbsolutePath() + File.separator + PROJECT_NAME + ".ipr");
@@ -62,6 +72,15 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
public void testKotlinProject() {
doTest();
+
+ assertOutputDeleted("src/test1.kt", "_DefaultPackage", "kotlinProject");
+ }
+
+ public void testKotlinProjectTwoFilesInOnePackage() {
+ doTest();
+
+ assertOutputDeleted("src/test1.kt", "_DefaultPackage", "kotlinProject");
+ assertOutputDeleted("src/test2.kt", "_DefaultPackage", "kotlinProject");
}
public void testKotlinJavaProject() {
@@ -106,14 +125,9 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
}
}
result.assertSuccessful();
- }
- public void testTestDependencyLibrary() throws Throwable {
- initProject();
- addKotlinRuntimeDependency(JpsJavaDependencyScope.TEST, myProject.getModules(), false);
- makeAll().assertSuccessful();
- change(workDir + "/src/src.kt", "fun foo() { println() }");
- makeAll().assertFailed();
+ assertOutputDeleted("src/kt2.kt", "kt2.Kt2Package", "kotlinProject");
+ assertOutputDeleted("module2/src/kt1.kt", "kt1.Kt1Package", "module2");
}
public void testReexportedDependency() {
@@ -133,7 +147,10 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
assertNotNull(outputUrl);
File outputDir = new File(JpsPathUtil.urlToPath(outputUrl));
File outputFile = new File(outputDir, relativePath);
- assertTrue("Output not written: " + outputFile.getAbsolutePath() + "\n Directory contents: \n" + dirContents(outputFile.getParentFile()),
+ assertTrue("Output not written: " +
+ outputFile.getAbsolutePath() +
+ "\n Directory contents: \n" +
+ dirContents(outputFile.getParentFile()),
outputFile.exists());
}
@@ -148,4 +165,25 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
}
return builder.toString();
}
+
+ private void assertOutputDeleted(String sourceFileName, String packageClassFqName, String moduleName) {
+ File file = new File(workDir, sourceFileName);
+ change(file.getAbsolutePath());
+ makeAll();
+
+ String outputDirPrefix = "out/production/" + moduleName + "/";
+ assertDeleted(outputDirPrefix + packageClassFqName.replace('.', '/') + ".class",
+ outputDirPrefix + getInternalNameForPackagePartClass(file, packageClassFqName) + ".class");
+ }
+
+ private static String getInternalNameForPackagePartClass(File sourceFile, String packageClassFqName) {
+ LightVirtualFile fakeVirtualFile = new LightVirtualFile(sourceFile.getPath()) {
+ @Override
+ public String getPath() {
+ // strip extra "/" from the beginning
+ return super.getPath().substring(1);
+ }
+ };
+ return NamespaceCodegen.getNamespacePartType(new FqName(packageClassFqName), fakeVirtualFile).getInternalName();
+ }
}
diff --git a/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/kotlinProject.iml b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/kotlinProject.iml
new file mode 100644
index 00000000000..a0cbe548242
--- /dev/null
+++ b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/kotlinProject.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/kotlinProject.ipr b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/kotlinProject.ipr
new file mode 100644
index 00000000000..90747786771
--- /dev/null
+++ b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/kotlinProject.ipr
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/src/test1.kt b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/src/test1.kt
new file mode 100644
index 00000000000..a2c4e958bb5
--- /dev/null
+++ b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/src/test1.kt
@@ -0,0 +1,3 @@
+fun foo() {
+
+}
\ No newline at end of file
diff --git a/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/src/test2.kt b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/src/test2.kt
new file mode 100644
index 00000000000..6ec77d22887
--- /dev/null
+++ b/jps-plugin/testData/KotlinProjectTwoFilesInOnePackage/src/test2.kt
@@ -0,0 +1,3 @@
+fun bar() {
+
+}
\ No newline at end of file