Support circular dependencies
We generate a module script with information on all modules in the chunk, then build the whole chunk as "one big module"
This commit is contained in:
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package org.jetbrains.jet.compiler.runner;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface KotlinModuleDescriptionBuilder {
|
||||||
|
KotlinModuleDescriptionBuilder addModule(
|
||||||
|
String moduleName,
|
||||||
|
String outputDir,
|
||||||
|
DependencyProvider dependencyProvider,
|
||||||
|
List<File> sourceFiles,
|
||||||
|
boolean tests,
|
||||||
|
Set<File> directoriesToFilterOut);
|
||||||
|
|
||||||
|
CharSequence asText();
|
||||||
|
|
||||||
|
interface DependencyProvider {
|
||||||
|
void processClassPath(DependencyProcessor processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DependencyProcessor {
|
||||||
|
void processClassPathSection(String sectionDescription, Collection<File> files);
|
||||||
|
void processAnnotationRoots(List<File> files);
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.compiler.runner;
|
||||||
|
|
||||||
|
public interface KotlinModuleDescriptionBuilderFactory {
|
||||||
|
KotlinModuleDescriptionBuilder create();
|
||||||
|
String getFileExtension();
|
||||||
|
}
|
||||||
-46
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.compiler.runner;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface KotlinModuleDescriptionGenerator {
|
|
||||||
CharSequence generateModuleScript(
|
|
||||||
String moduleName,
|
|
||||||
String outputDir,
|
|
||||||
DependencyProvider dependencyProvider,
|
|
||||||
List<File> sourceFiles,
|
|
||||||
boolean tests,
|
|
||||||
Set<File> directoriesToFilterOut
|
|
||||||
);
|
|
||||||
|
|
||||||
String getFileExtension();
|
|
||||||
|
|
||||||
interface DependencyProvider {
|
|
||||||
void processClassPath(@NotNull DependencyProcessor processor);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DependencyProcessor {
|
|
||||||
void processClassPathSection(@NotNull String sectionDescription, @NotNull Collection<File> files);
|
|
||||||
void processAnnotationRoots(@NotNull List<File> files);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.compiler.runner;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
|
||||||
|
|
||||||
|
public class KotlinModuleScriptBuilderFactory implements KotlinModuleDescriptionBuilderFactory {
|
||||||
|
|
||||||
|
public static final KotlinModuleScriptBuilderFactory INSTANCE = new KotlinModuleScriptBuilderFactory();
|
||||||
|
|
||||||
|
private KotlinModuleScriptBuilderFactory() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KotlinModuleDescriptionBuilder create() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFileExtension() {
|
||||||
|
return "kts";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Builder implements KotlinModuleDescriptionBuilder {
|
||||||
|
private final StringBuilder script = new StringBuilder();
|
||||||
|
private boolean done = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
script.append("import kotlin.modules.*\n");
|
||||||
|
script.append("fun project() {\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KotlinModuleDescriptionBuilder addModule(
|
||||||
|
String moduleName,
|
||||||
|
String outputDir,
|
||||||
|
DependencyProvider dependencyProvider,
|
||||||
|
List<File> sourceFiles,
|
||||||
|
boolean tests,
|
||||||
|
final Set<File> directoriesToFilterOut
|
||||||
|
) {
|
||||||
|
assert !done : "Already done";
|
||||||
|
|
||||||
|
if (tests) {
|
||||||
|
script.append("// Module script for tests\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
script.append("// Module script for production\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
script.append(" module(\"" + moduleName + "\", outputDir = \"" + toSystemIndependentName(outputDir) + "\") {\n");
|
||||||
|
|
||||||
|
for (File sourceFile : sourceFiles) {
|
||||||
|
script.append(" sources += \"" + toSystemIndependentName(sourceFile.getPath()) + "\"\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyProvider.processClassPath(new DependencyProcessor() {
|
||||||
|
@Override
|
||||||
|
public void processClassPathSection(@NotNull String sectionDescription, @NotNull Collection<File> files) {
|
||||||
|
script.append(" // " + sectionDescription + "\n");
|
||||||
|
for (File file : files) {
|
||||||
|
if (directoriesToFilterOut.contains(file)) {
|
||||||
|
// For IDEA's make (incremental compilation) purposes, output directories of the current module and its dependencies
|
||||||
|
// appear on the class path, so we are at risk of seeing the results of the previous build, i.e. if some class was
|
||||||
|
// removed in the sources, it may still be there in binaries. Thus, we delete these entries from the classpath.
|
||||||
|
script.append(" // Output directory, commented out\n");
|
||||||
|
script.append(" // ");
|
||||||
|
}
|
||||||
|
script.append(" classpath += \"" + toSystemIndependentName(file.getPath()) + "\"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processAnnotationRoots(@NotNull List<File> files) {
|
||||||
|
script.append(" // External annotations\n");
|
||||||
|
for (File file : files) {
|
||||||
|
script.append(" annotationsPath += \"").append(toSystemIndependentName(file.getPath())).append("\"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
script.append(" }\n");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence asText() {
|
||||||
|
if (!done) {
|
||||||
|
script.append("}\n");
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
-93
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.compiler.runner;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
|
|
||||||
|
|
||||||
public class KotlinModuleScriptGenerator implements KotlinModuleDescriptionGenerator {
|
|
||||||
|
|
||||||
public static final KotlinModuleScriptGenerator INSTANCE = new KotlinModuleScriptGenerator();
|
|
||||||
|
|
||||||
private KotlinModuleScriptGenerator() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence generateModuleScript(
|
|
||||||
String moduleName,
|
|
||||||
String outputDir, DependencyProvider dependencyProvider,
|
|
||||||
List<File> sourceFiles,
|
|
||||||
boolean tests,
|
|
||||||
final Set<File> directoriesToFilterOut
|
|
||||||
) {
|
|
||||||
final StringBuilder script = new StringBuilder();
|
|
||||||
|
|
||||||
if (tests) {
|
|
||||||
script.append("// Module script for tests\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
script.append("// Module script for production\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
script.append("import kotlin.modules.*\n");
|
|
||||||
script.append("fun project() {\n");
|
|
||||||
script.append(" module(\"" + moduleName + "\", outputDir = \"" + toSystemIndependentName(outputDir) + "\") {\n");
|
|
||||||
|
|
||||||
for (File sourceFile : sourceFiles) {
|
|
||||||
script.append(" sources += \"" + toSystemIndependentName(sourceFile.getPath()) + "\"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyProvider.processClassPath(new DependencyProcessor() {
|
|
||||||
@Override
|
|
||||||
public void processClassPathSection(@NotNull String sectionDescription, @NotNull Collection<File> files) {
|
|
||||||
script.append(" // " + sectionDescription + "\n");
|
|
||||||
for (File file : files) {
|
|
||||||
if (directoriesToFilterOut.contains(file)) {
|
|
||||||
// For IDEA's make (incremental compilation) purposes, output directories of the current module and its dependencies
|
|
||||||
// appear on the class path, so we are at risk of seeing the results of the previous build, i.e. if some class was
|
|
||||||
// removed in the sources, it may still be there in binaries. Thus, we delete these entries from the classpath.
|
|
||||||
script.append(" // Output directory, commented out\n");
|
|
||||||
script.append(" // ");
|
|
||||||
}
|
|
||||||
script.append(" classpath += \"" + toSystemIndependentName(file.getPath()) + "\"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processAnnotationRoots(@NotNull List<File> files) {
|
|
||||||
script.append(" // External annotations\n");
|
|
||||||
for (File file : files) {
|
|
||||||
script.append(" annotationsPath += \"").append(toSystemIndependentName(file.getPath())).append("\"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
script.append(" }\n");
|
|
||||||
script.append("}\n");
|
|
||||||
return script;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFileExtension() {
|
|
||||||
return "kts";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+143
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.compiler.runner;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.utils.Printer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
|
||||||
|
import static com.intellij.openapi.util.text.StringUtil.escapeXml;
|
||||||
|
import static org.jetbrains.jet.cli.common.modules.ModuleXmlParser.*;
|
||||||
|
|
||||||
|
public class KotlinModuleXmlBuilderFactory implements KotlinModuleDescriptionBuilderFactory {
|
||||||
|
|
||||||
|
public static final KotlinModuleXmlBuilderFactory INSTANCE = new KotlinModuleXmlBuilderFactory();
|
||||||
|
|
||||||
|
private KotlinModuleXmlBuilderFactory() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KotlinModuleDescriptionBuilder create() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFileExtension() {
|
||||||
|
return "xml";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Builder implements KotlinModuleDescriptionBuilder {
|
||||||
|
private final StringBuilder xml = new StringBuilder();
|
||||||
|
private final Printer p = new Printer(xml);
|
||||||
|
private boolean done = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
openTag(p, MODULES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KotlinModuleDescriptionBuilder addModule(
|
||||||
|
String moduleName,
|
||||||
|
String outputDir,
|
||||||
|
DependencyProvider dependencyProvider,
|
||||||
|
List<File> sourceFiles,
|
||||||
|
boolean tests,
|
||||||
|
final Set<File> directoriesToFilterOut
|
||||||
|
) {
|
||||||
|
assert !done : "Already done";
|
||||||
|
|
||||||
|
if (tests) {
|
||||||
|
p.println("<!-- Module script for tests -->");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.println("<!-- Module script for production -->");
|
||||||
|
}
|
||||||
|
|
||||||
|
p.println("<", MODULE, " ",
|
||||||
|
NAME, "=\"", escapeXml(moduleName), "\" ",
|
||||||
|
OUTPUT_DIR, "=\"", getEscapedPath(new File(outputDir)), "\">");
|
||||||
|
p.pushIndent();
|
||||||
|
|
||||||
|
for (File sourceFile : sourceFiles) {
|
||||||
|
p.println("<", SOURCES, " ", PATH, "=\"", getEscapedPath(sourceFile), "\"/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyProvider.processClassPath(new DependencyProcessor() {
|
||||||
|
@Override
|
||||||
|
public void processClassPathSection(@NotNull String sectionDescription, @NotNull Collection<File> files) {
|
||||||
|
p.println("<!-- ", sectionDescription, " -->");
|
||||||
|
for (File file : files) {
|
||||||
|
boolean isOutput = directoriesToFilterOut.contains(file);
|
||||||
|
if (isOutput) {
|
||||||
|
// For IDEA's make (incremental compilation) purposes, output directories of the current module and its dependencies
|
||||||
|
// appear on the class path, so we are at risk of seeing the results of the previous build, i.e. if some class was
|
||||||
|
// removed in the sources, it may still be there in binaries. Thus, we delete these entries from the classpath.
|
||||||
|
p.println("<!-- Output directory, commented out -->");
|
||||||
|
p.println("<!-- ");
|
||||||
|
p.pushIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
p.println("<", CLASSPATH, " ", PATH, "=\"", getEscapedPath(file), "\"/>");
|
||||||
|
|
||||||
|
if (isOutput) {
|
||||||
|
p.popIndent();
|
||||||
|
p.println("-->");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processAnnotationRoots(@NotNull List<File> files) {
|
||||||
|
p.println("<!-- External annotations -->");
|
||||||
|
for (File file : files) {
|
||||||
|
p.println("<", EXTERNAL_ANNOTATIONS, " ", PATH, "= \"", getEscapedPath(file), "\"/>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
closeTag(p, MODULE);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CharSequence asText() {
|
||||||
|
if (!done) {
|
||||||
|
closeTag(p, MODULES);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void openTag(Printer p, String tag) {
|
||||||
|
p.println("<" + tag + ">");
|
||||||
|
p.pushIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void closeTag(Printer p, String tag) {
|
||||||
|
p.popIndent();
|
||||||
|
p.println("</" + tag + ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getEscapedPath(File sourceFile) {
|
||||||
|
return escapeXml(toSystemIndependentName(sourceFile.getPath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
-123
@@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2013 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.jet.compiler.runner;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.utils.Printer;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
|
|
||||||
import static com.intellij.openapi.util.text.StringUtil.escapeXml;
|
|
||||||
import static org.jetbrains.jet.cli.common.modules.ModuleXmlParser.*;
|
|
||||||
|
|
||||||
public class KotlinModuleXmlGenerator implements KotlinModuleDescriptionGenerator {
|
|
||||||
|
|
||||||
public static final KotlinModuleXmlGenerator INSTANCE = new KotlinModuleXmlGenerator();
|
|
||||||
|
|
||||||
private KotlinModuleXmlGenerator() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CharSequence generateModuleScript(
|
|
||||||
String moduleName,
|
|
||||||
String outputDir, DependencyProvider dependencyProvider,
|
|
||||||
List<File> sourceFiles,
|
|
||||||
boolean tests,
|
|
||||||
final Set<File> directoriesToFilterOut
|
|
||||||
) {
|
|
||||||
StringBuilder xml = new StringBuilder();
|
|
||||||
final Printer p = new Printer(xml);
|
|
||||||
|
|
||||||
openTag(p, MODULES);
|
|
||||||
|
|
||||||
if (tests) {
|
|
||||||
p.println("<!-- Module script for tests -->");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.println("<!-- Module script for production -->");
|
|
||||||
}
|
|
||||||
|
|
||||||
p.println("<", MODULE, " ",
|
|
||||||
NAME, "=\"", escapeXml(moduleName), "\" ",
|
|
||||||
OUTPUT_DIR, "=\"", getEscapedPath(new File(outputDir)), "\">");
|
|
||||||
p.pushIndent();
|
|
||||||
|
|
||||||
for (File sourceFile : sourceFiles) {
|
|
||||||
p.println("<", SOURCES, " ", PATH, "=\"", getEscapedPath(sourceFile), "\"/>");
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyProvider.processClassPath(new DependencyProcessor() {
|
|
||||||
@Override
|
|
||||||
public void processClassPathSection(@NotNull String sectionDescription, @NotNull Collection<File> files) {
|
|
||||||
p.println("<!-- ", sectionDescription, " -->");
|
|
||||||
for (File file : files) {
|
|
||||||
boolean isOutput = directoriesToFilterOut.contains(file);
|
|
||||||
if (isOutput) {
|
|
||||||
// For IDEA's make (incremental compilation) purposes, output directories of the current module and its dependencies
|
|
||||||
// appear on the class path, so we are at risk of seeing the results of the previous build, i.e. if some class was
|
|
||||||
// removed in the sources, it may still be there in binaries. Thus, we delete these entries from the classpath.
|
|
||||||
p.println("<!-- Output directory, commented out -->");
|
|
||||||
p.println("<!-- ");
|
|
||||||
p.pushIndent();
|
|
||||||
}
|
|
||||||
|
|
||||||
p.println("<", CLASSPATH, " ", PATH, "=\"", getEscapedPath(file), "\"/>");
|
|
||||||
|
|
||||||
if (isOutput) {
|
|
||||||
p.popIndent();
|
|
||||||
p.println("-->");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processAnnotationRoots(@NotNull List<File> files) {
|
|
||||||
p.println("<!-- External annotations -->");
|
|
||||||
for (File file : files) {
|
|
||||||
p.println("<", EXTERNAL_ANNOTATIONS, " ", PATH, "= \"", getEscapedPath(file), "\"/>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
closeTag(p, MODULE);
|
|
||||||
|
|
||||||
closeTag(p, MODULES);
|
|
||||||
return xml;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getFileExtension() {
|
|
||||||
return "xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void openTag(Printer p, String tag) {
|
|
||||||
p.println("<" + tag + ">");
|
|
||||||
p.pushIndent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void closeTag(Printer p, String tag) {
|
|
||||||
p.popIndent();
|
|
||||||
p.println("</" + tag + ">");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getEscapedPath(File sourceFile) {
|
|
||||||
return escapeXml(toSystemIndependentName(sourceFile.getPath()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -157,14 +157,14 @@ public class JetCompiler implements TranslatingCompiler {
|
|||||||
if (!tests) {
|
if (!tests) {
|
||||||
outputDirectoriesToFilter.add(moduleOutputDirectory);
|
outputDirectoriesToFilter.add(moduleOutputDirectory);
|
||||||
}
|
}
|
||||||
CharSequence script = KotlinModuleScriptGenerator.INSTANCE.generateModuleScript(
|
CharSequence script = KotlinModuleScriptBuilderFactory.INSTANCE.create().addModule(
|
||||||
moduleName,
|
moduleName,
|
||||||
moduleOutputDirectory.getAbsolutePath(),
|
moduleOutputDirectory.getAbsolutePath(),
|
||||||
getDependencyProvider(chunk, tests, mainOutput),
|
getDependencyProvider(chunk, tests, mainOutput),
|
||||||
sourceFiles,
|
sourceFiles,
|
||||||
tests,
|
tests,
|
||||||
outputDirectoriesToFilter
|
outputDirectoriesToFilter
|
||||||
);
|
).asText();
|
||||||
|
|
||||||
File scriptFile = new File(outputDir, "script.kts");
|
File scriptFile = new File(outputDir, "script.kts");
|
||||||
try {
|
try {
|
||||||
@@ -177,14 +177,14 @@ public class JetCompiler implements TranslatingCompiler {
|
|||||||
return scriptFile;
|
return scriptFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KotlinModuleDescriptionGenerator.DependencyProvider getDependencyProvider(
|
private static KotlinModuleDescriptionBuilder.DependencyProvider getDependencyProvider(
|
||||||
final ModuleChunk chunk,
|
final ModuleChunk chunk,
|
||||||
final boolean tests,
|
final boolean tests,
|
||||||
final VirtualFile mainOutputPath
|
final VirtualFile mainOutputPath
|
||||||
) {
|
) {
|
||||||
return new KotlinModuleDescriptionGenerator.DependencyProvider() {
|
return new KotlinModuleDescriptionBuilder.DependencyProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void processClassPath(@NotNull KotlinModuleDescriptionGenerator.DependencyProcessor processor) {
|
public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) {
|
||||||
// TODO: have a bootclasspath in script API
|
// TODO: have a bootclasspath in script API
|
||||||
processor.processClassPathSection("Boot classpath", ioFiles(chunk.getCompilationBootClasspathFiles()));
|
processor.processClassPathSection("Boot classpath", ioFiles(chunk.getCompilationBootClasspathFiles()));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<modules>
|
||||||
|
<!-- Module script for production -->
|
||||||
|
<module name="name" outputDir="output">
|
||||||
|
<sources path="s1"/>
|
||||||
|
<sources path="s2"/>
|
||||||
|
<!-- External annotations -->
|
||||||
|
<externalAnnotations path= "a1/f1"/>
|
||||||
|
<externalAnnotations path= "a2"/>
|
||||||
|
<!-- s1 -->
|
||||||
|
<!-- Output directory, commented out -->
|
||||||
|
<!--
|
||||||
|
<classpath path="cp1"/>
|
||||||
|
-->
|
||||||
|
<classpath path="cp2"/>
|
||||||
|
</module>
|
||||||
|
<!-- Module script for tests -->
|
||||||
|
<module name="name2" outputDir="output2">
|
||||||
|
<sources path="s12"/>
|
||||||
|
<sources path="s22"/>
|
||||||
|
<!-- External annotations -->
|
||||||
|
<externalAnnotations path= "a12/f12"/>
|
||||||
|
<externalAnnotations path= "a22"/>
|
||||||
|
<!-- s12 -->
|
||||||
|
<!-- Output directory, commented out -->
|
||||||
|
<!--
|
||||||
|
<classpath path="cp12"/>
|
||||||
|
-->
|
||||||
|
<classpath path="cp22"/>
|
||||||
|
</module>
|
||||||
|
</modules>
|
||||||
@@ -20,8 +20,9 @@ import com.intellij.openapi.util.io.FileUtil;
|
|||||||
import com.intellij.testFramework.UsefulTestCase;
|
import com.intellij.testFramework.UsefulTestCase;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionGenerator;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.compiler.runner.KotlinModuleXmlGenerator;
|
import org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionBuilder;
|
||||||
|
import org.jetbrains.jet.compiler.runner.KotlinModuleXmlBuilderFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -29,38 +30,70 @@ import java.util.Collections;
|
|||||||
|
|
||||||
public class KotlinModuleXmlGeneratorTest extends TestCase {
|
public class KotlinModuleXmlGeneratorTest extends TestCase {
|
||||||
public void testBasic() throws Exception {
|
public void testBasic() throws Exception {
|
||||||
String actual = KotlinModuleXmlGenerator.INSTANCE.generateModuleScript(
|
String actual = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule(
|
||||||
"name",
|
"name",
|
||||||
"output",
|
"output",
|
||||||
new KotlinModuleDescriptionGenerator.DependencyProvider() {
|
new KotlinModuleDescriptionBuilder.DependencyProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void processClassPath(@NotNull KotlinModuleDescriptionGenerator.DependencyProcessor processor) {
|
public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) {
|
||||||
processor.processAnnotationRoots(Arrays.asList(new File("a1/f1"), new File("a2")));
|
processor.processAnnotationRoots(Arrays.asList(new File("a1/f1"), new File("a2")));
|
||||||
processor.processClassPathSection("s1", Arrays.asList(new File("cp1"), new File("cp2")));
|
processor.processClassPathSection("s1", Arrays.asList(new File("cp1"), new File("cp2")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Arrays.asList(new File("s1"), new File("s2")),
|
Arrays.asList(new File("s1"), new File("s2")),
|
||||||
false,
|
false,
|
||||||
Collections.<File>emptySet()).toString();
|
Collections.<File>emptySet()).asText().toString();
|
||||||
String expected = FileUtil.loadFile(new File("idea/testData/modules.xml/basic.xml"));
|
String expected = FileUtil.loadFile(new File("idea/testData/modules.xml/basic.xml"));
|
||||||
UsefulTestCase.assertSameLines(expected, actual);
|
UsefulTestCase.assertSameLines(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFiltered() throws Exception {
|
public void testFiltered() throws Exception {
|
||||||
String actual = KotlinModuleXmlGenerator.INSTANCE.generateModuleScript(
|
String actual = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule(
|
||||||
"name",
|
"name",
|
||||||
"output",
|
"output",
|
||||||
new KotlinModuleDescriptionGenerator.DependencyProvider() {
|
new KotlinModuleDescriptionBuilder.DependencyProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void processClassPath(@NotNull KotlinModuleDescriptionGenerator.DependencyProcessor processor) {
|
public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) {
|
||||||
processor.processAnnotationRoots(Arrays.asList(new File("a1/f1"), new File("a2")));
|
processor.processAnnotationRoots(Arrays.asList(new File("a1/f1"), new File("a2")));
|
||||||
processor.processClassPathSection("s1", Arrays.asList(new File("cp1"), new File("cp2")));
|
processor.processClassPathSection("s1", Arrays.asList(new File("cp1"), new File("cp2")));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Arrays.asList(new File("s1"), new File("s2")),
|
Arrays.asList(new File("s1"), new File("s2")),
|
||||||
false,
|
false,
|
||||||
Collections.singleton(new File("cp1"))).toString();
|
Collections.singleton(new File("cp1"))).asText().toString();
|
||||||
String expected = FileUtil.loadFile(new File("idea/testData/modules.xml/filtered.xml"));
|
String expected = FileUtil.loadFile(new File("idea/testData/modules.xml/filtered.xml"));
|
||||||
UsefulTestCase.assertSameLines(expected, actual);
|
UsefulTestCase.assertSameLines(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMultiple() throws Exception {
|
||||||
|
KotlinModuleDescriptionBuilder builder = KotlinModuleXmlBuilderFactory.INSTANCE.create();
|
||||||
|
builder.addModule(
|
||||||
|
"name",
|
||||||
|
"output",
|
||||||
|
new KotlinModuleDescriptionBuilder.DependencyProvider() {
|
||||||
|
@Override
|
||||||
|
public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) {
|
||||||
|
processor.processAnnotationRoots(Arrays.asList(new File("a1/f1"), new File("a2")));
|
||||||
|
processor.processClassPathSection("s1", Arrays.asList(new File("cp1"), new File("cp2")));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Arrays.asList(new File("s1"), new File("s2")),
|
||||||
|
false,
|
||||||
|
Collections.singleton(new File("cp1")));
|
||||||
|
builder.addModule(
|
||||||
|
"name2",
|
||||||
|
"output2",
|
||||||
|
new KotlinModuleDescriptionBuilder.DependencyProvider() {
|
||||||
|
@Override
|
||||||
|
public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) {
|
||||||
|
processor.processAnnotationRoots(Arrays.asList(new File("a12/f12"), new File("a22")));
|
||||||
|
processor.processClassPathSection("s12", Arrays.asList(new File("cp12"), new File("cp22")));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Arrays.asList(new File("s12"), new File("s22")),
|
||||||
|
true,
|
||||||
|
Collections.singleton(new File("cp12")));
|
||||||
|
String actual = builder.asText().toString();
|
||||||
|
JetTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/multiple.xml"), actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,13 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.*;
|
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.EXCEPTION;
|
||||||
|
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.INFO;
|
||||||
|
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.WARNING;
|
||||||
|
|
||||||
public class KotlinBuilder extends ModuleLevelBuilder {
|
public class KotlinBuilder extends ModuleLevelBuilder {
|
||||||
|
|
||||||
@@ -81,29 +85,12 @@ public class KotlinBuilder extends ModuleLevelBuilder {
|
|||||||
|
|
||||||
messageCollector.report(INFO, "Kotlin JPS plugin version " + KotlinVersion.VERSION, CompilerMessageLocation.NO_LOCATION);
|
messageCollector.report(INFO, "Kotlin JPS plugin version " + KotlinVersion.VERSION, CompilerMessageLocation.NO_LOCATION);
|
||||||
|
|
||||||
if (chunk.getModules().size() > 1) {
|
|
||||||
// We do not support circular dependencies, but if they are present, we should not break the build,
|
|
||||||
// so we simply yield a warning and report NOTHING_DONE
|
|
||||||
messageCollector.report(
|
|
||||||
WARNING, "Circular dependencies are not supported. " +
|
|
||||||
"The following modules depend on each other: " + StringUtil.join(chunk.getModules(), MODULE_NAME, ", ") + ". " +
|
|
||||||
"Kotlin is not compiled for these modules",
|
|
||||||
CompilerMessageLocation.NO_LOCATION);
|
|
||||||
return ExitCode.NOTHING_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModuleBuildTarget representativeTarget = chunk.representativeTarget();
|
ModuleBuildTarget representativeTarget = chunk.representativeTarget();
|
||||||
|
|
||||||
// For non-incremental build: take all sources
|
// For non-incremental build: take all sources
|
||||||
if (!dirtyFilesHolder.hasDirtyFiles()) {
|
if (!dirtyFilesHolder.hasDirtyFiles()) {
|
||||||
return ExitCode.NOTHING_DONE;
|
return ExitCode.NOTHING_DONE;
|
||||||
}
|
}
|
||||||
List<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(representativeTarget);
|
|
||||||
//List<File> sourceFiles = KotlinSourceFileCollector.getDirtySourceFiles(dirtyFilesHolder);
|
|
||||||
|
|
||||||
if (sourceFiles.isEmpty()) {
|
|
||||||
return ExitCode.NOTHING_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
File outputDir = representativeTarget.getOutputDir();
|
File outputDir = representativeTarget.getOutputDir();
|
||||||
|
|
||||||
@@ -118,6 +105,24 @@ public class KotlinBuilder extends ModuleLevelBuilder {
|
|||||||
OutputItemsCollectorImpl outputItemCollector = new OutputItemsCollectorImpl(outputDir);
|
OutputItemsCollectorImpl outputItemCollector = new OutputItemsCollectorImpl(outputDir);
|
||||||
|
|
||||||
if (JpsUtils.isJsKotlinModule(representativeTarget)) {
|
if (JpsUtils.isJsKotlinModule(representativeTarget)) {
|
||||||
|
if (chunk.getModules().size() > 1) {
|
||||||
|
// We do not support circular dependencies, but if they are present, we do our best should not break the build,
|
||||||
|
// so we simply yield a warning and report NOTHING_DONE
|
||||||
|
messageCollector.report(
|
||||||
|
WARNING, "Circular dependencies are not supported. " +
|
||||||
|
"The following JS modules depend on each other: " + StringUtil.join(chunk.getModules(), MODULE_NAME, ", ") + ". " +
|
||||||
|
"Kotlin is not compiled for these modules",
|
||||||
|
CompilerMessageLocation.NO_LOCATION);
|
||||||
|
return ExitCode.NOTHING_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(representativeTarget);
|
||||||
|
//List<File> sourceFiles = KotlinSourceFileCollector.getDirtySourceFiles(dirtyFilesHolder);
|
||||||
|
|
||||||
|
if (sourceFiles.isEmpty()) {
|
||||||
|
return ExitCode.NOTHING_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
File outputFile = new File(outputDir, representativeTarget.getModule().getName() + ".js");
|
File outputFile = new File(outputDir, representativeTarget.getModule().getName() + ".js");
|
||||||
|
|
||||||
KotlinCompilerRunner.runK2JsCompiler(
|
KotlinCompilerRunner.runK2JsCompiler(
|
||||||
@@ -129,7 +134,19 @@ public class KotlinBuilder extends ModuleLevelBuilder {
|
|||||||
outputFile);
|
outputFile);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
File moduleFile = KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, representativeTarget, sourceFiles);
|
if (chunk.getModules().size() > 1) {
|
||||||
|
messageCollector.report(
|
||||||
|
WARNING, "Circular dependencies are only partially supported. " +
|
||||||
|
"The following modules depend on each other: " + StringUtil.join(chunk.getModules(), MODULE_NAME, ", ") + ". " +
|
||||||
|
"Kotlin will compile them, but some strange effect may happen",
|
||||||
|
CompilerMessageLocation.NO_LOCATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
File moduleFile = KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, chunk);
|
||||||
|
if (moduleFile == null) {
|
||||||
|
// No Kotlin sources found
|
||||||
|
return ExitCode.NOTHING_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
KotlinCompilerRunner.runK2JvmCompiler(
|
KotlinCompilerRunner.runK2JvmCompiler(
|
||||||
messageCollector,
|
messageCollector,
|
||||||
|
|||||||
+45
-23
@@ -20,14 +20,17 @@ import com.intellij.openapi.util.io.FileUtil;
|
|||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionGenerator;
|
import org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionBuilder;
|
||||||
import org.jetbrains.jet.compiler.runner.KotlinModuleXmlGenerator;
|
import org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionBuilderFactory;
|
||||||
|
import org.jetbrains.jet.compiler.runner.KotlinModuleXmlBuilderFactory;
|
||||||
|
import org.jetbrains.jps.ModuleChunk;
|
||||||
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
|
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
|
||||||
import org.jetbrains.jps.incremental.CompileContext;
|
import org.jetbrains.jps.incremental.CompileContext;
|
||||||
import org.jetbrains.jps.incremental.ModuleBuildTarget;
|
import org.jetbrains.jps.incremental.ModuleBuildTarget;
|
||||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||||
import org.jetbrains.jps.model.java.*;
|
import org.jetbrains.jps.model.java.JpsAnnotationRootType;
|
||||||
|
import org.jetbrains.jps.model.java.JpsJavaSdkType;
|
||||||
import org.jetbrains.jps.model.library.JpsLibrary;
|
import org.jetbrains.jps.model.library.JpsLibrary;
|
||||||
import org.jetbrains.jps.model.library.sdk.JpsSdk;
|
import org.jetbrains.jps.model.library.sdk.JpsSdk;
|
||||||
import org.jetbrains.jps.model.library.sdk.JpsSdkType;
|
import org.jetbrains.jps.model.library.sdk.JpsSdkType;
|
||||||
@@ -42,42 +45,61 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionGenerator.DependencyProvider;
|
import static org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionBuilder.DependencyProcessor;
|
||||||
|
import static org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionBuilder.DependencyProvider;
|
||||||
import static org.jetbrains.jet.jps.build.JpsUtils.getAllDependencies;
|
import static org.jetbrains.jet.jps.build.JpsUtils.getAllDependencies;
|
||||||
|
|
||||||
public class KotlinBuilderModuleScriptGenerator {
|
public class KotlinBuilderModuleScriptGenerator {
|
||||||
|
|
||||||
public static final KotlinModuleDescriptionGenerator GENERATOR = KotlinModuleXmlGenerator.INSTANCE;
|
public static final KotlinModuleDescriptionBuilderFactory FACTORY = KotlinModuleXmlBuilderFactory.INSTANCE;
|
||||||
|
|
||||||
public static File generateModuleDescription(CompileContext context, ModuleBuildTarget target, List<File> sourceFiles)
|
@Nullable
|
||||||
|
public static File generateModuleDescription(CompileContext context, ModuleChunk chunk)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
|
KotlinModuleDescriptionBuilder builder = FACTORY.create();
|
||||||
|
|
||||||
|
boolean noSources = true;
|
||||||
|
|
||||||
|
for (ModuleBuildTarget target : chunk.getTargets()) {
|
||||||
|
File outputDir = getOutputDir(target);
|
||||||
|
|
||||||
|
List<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(target);
|
||||||
|
noSources &= sourceFiles.isEmpty();
|
||||||
|
|
||||||
|
builder.addModule(
|
||||||
|
target.getId(),
|
||||||
|
outputDir.getAbsolutePath(),
|
||||||
|
getKotlinModuleDependencies(context, target),
|
||||||
|
sourceFiles,
|
||||||
|
target.isTests(),
|
||||||
|
// this excludes the output directory from the class path, to be removed for true incremental compilation
|
||||||
|
Collections.singleton(outputDir)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noSources) return null;
|
||||||
|
|
||||||
|
File scriptFile = new File(getOutputDir(chunk.representativeTarget()), "script." + FACTORY.getFileExtension());
|
||||||
|
|
||||||
|
writeScriptToFile(context, builder.asText(), scriptFile);
|
||||||
|
|
||||||
|
return scriptFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static File getOutputDir(@NotNull ModuleBuildTarget target) {
|
||||||
File outputDir = target.getOutputDir();
|
File outputDir = target.getOutputDir();
|
||||||
if (outputDir == null) {
|
if (outputDir == null) {
|
||||||
throw new IllegalStateException("No output directory found for " + target);
|
throw new IllegalStateException("No output directory found for " + target);
|
||||||
|
|
||||||
}
|
}
|
||||||
CharSequence moduleScriptText = GENERATOR.generateModuleScript(
|
return outputDir;
|
||||||
target.getId(),
|
|
||||||
outputDir.getAbsolutePath(),
|
|
||||||
getKotlinModuleDependencies(context, target),
|
|
||||||
sourceFiles,
|
|
||||||
target.isTests(),
|
|
||||||
// this excludes the output directory from the class path, to be removed for true incremental compilation
|
|
||||||
Collections.singleton(outputDir)
|
|
||||||
);
|
|
||||||
|
|
||||||
File scriptFile = new File(outputDir, "script." + GENERATOR.getFileExtension());
|
|
||||||
|
|
||||||
writeScriptToFile(context, moduleScriptText, scriptFile);
|
|
||||||
|
|
||||||
return scriptFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DependencyProvider getKotlinModuleDependencies(final CompileContext context, final ModuleBuildTarget target) {
|
private static DependencyProvider getKotlinModuleDependencies(final CompileContext context, final ModuleBuildTarget target) {
|
||||||
return new DependencyProvider() {
|
return new DependencyProvider() {
|
||||||
@Override
|
@Override
|
||||||
public void processClassPath(@NotNull KotlinModuleDescriptionGenerator.DependencyProcessor processor) {
|
public void processClassPath(@NotNull DependencyProcessor processor) {
|
||||||
processor.processClassPathSection("Classpath", findClassPathRoots(target));
|
processor.processClassPathSection("Classpath", findClassPathRoots(target));
|
||||||
processor.processClassPathSection("Java Source Roots", findSourceRoots(context, target));
|
processor.processClassPathSection("Java Source Roots", findSourceRoots(context, target));
|
||||||
processor.processAnnotationRoots(findAnnotationRoots(target));
|
processor.processAnnotationRoots(findAnnotationRoots(target));
|
||||||
|
|||||||
@@ -19,8 +19,11 @@ package org.jetbrains.jet.jps.build;
|
|||||||
import com.intellij.openapi.util.Condition;
|
import com.intellij.openapi.util.Condition;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.jps.model.java.*;
|
import org.jetbrains.jps.builders.BuildResult;
|
||||||
|
import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
|
||||||
|
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||||
import org.jetbrains.jps.model.module.JpsModule;
|
import org.jetbrains.jps.model.module.JpsModule;
|
||||||
|
import org.jetbrains.jps.util.JpsPathUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -89,6 +92,22 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCircularDependenciesWithKotlinFilesDifferentPackages() {
|
||||||
|
initProject();
|
||||||
|
BuildResult result = makeAll();
|
||||||
|
|
||||||
|
// Check that outputs are located properly
|
||||||
|
for (JpsModule module : myProject.getModules()) {
|
||||||
|
if (module.getName().equals("module2")) {
|
||||||
|
assertFileExistsInOutput(module, "kt1/Kt1Package.class");
|
||||||
|
}
|
||||||
|
if (module.getName().equals("kotlinProject")) {
|
||||||
|
assertFileExistsInOutput(module, "kt2/Kt2Package.class");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
public void testTestDependencyLibrary() throws Throwable {
|
public void testTestDependencyLibrary() throws Throwable {
|
||||||
initProject();
|
initProject();
|
||||||
addKotlinRuntimeDependency(JpsJavaDependencyScope.TEST, myProject.getModules(), false);
|
addKotlinRuntimeDependency(JpsJavaDependencyScope.TEST, myProject.getModules(), false);
|
||||||
@@ -109,4 +128,24 @@ public class KotlinJpsBuildTestCase extends AbstractKotlinJpsBuildTestCase {
|
|||||||
makeAll().assertSuccessful();
|
makeAll().assertSuccessful();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void assertFileExistsInOutput(JpsModule module, String relativePath) {
|
||||||
|
String outputUrl = JpsJavaExtensionService.getInstance().getOutputUrl(module, false);
|
||||||
|
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()),
|
||||||
|
outputFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String dirContents(File dir) {
|
||||||
|
File[] files = dir.listFiles();
|
||||||
|
if (files == null) {
|
||||||
|
return "<not found>";
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (File file : files) {
|
||||||
|
builder.append(" * ").append(file.getName()).append("\n");
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
<?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" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="KotlinRuntime" level="project" />
|
||||||
|
<orderEntry type="module" module-name="module2" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
|
|
||||||
+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$/kotlinProject.iml" filepath="$PROJECT_DIR$/kotlinProject.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>
|
||||||
|
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
<?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" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="IDEA_JDK" jdkType="JavaSDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="module" module-name="kotlinProject" />
|
||||||
|
<orderEntry type="library" name="KotlinRuntime" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
|
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
public class JSecond {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new JFirst().foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package kt1
|
||||||
|
|
||||||
|
fun foo() {}
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
kt2.bar()
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
public class JFirst {
|
||||||
|
JSecond s = null;
|
||||||
|
|
||||||
|
public void foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package kt2
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
kt1.foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar() {}
|
||||||
Reference in New Issue
Block a user