Moved parts of ide-compiler-runner to direct modules.
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
<orderEntry type="module" module-name="cli-common" />
|
||||
<orderEntry type="library" name="jps" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="jps-test" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="idea-full" level="project" />
|
||||
<orderEntry type="library" name="idea-full" level="project" />
|
||||
<orderEntry type="module" module-name="backend" scope="TEST" />
|
||||
<orderEntry type="module" module-name="descriptors" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ComparatorUtil;
|
||||
import com.sampullara.cli.Argument;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArgumentUtils {
|
||||
private ArgumentUtils() {}
|
||||
|
||||
@NotNull
|
||||
public static List<String> convertArgumentsToStringList(@NotNull CommonCompilerArguments arguments)
|
||||
throws InstantiationException, IllegalAccessException {
|
||||
List<String> result = new ArrayList<String>();
|
||||
convertArgumentsToStringList(arguments, arguments.getClass().newInstance(), arguments.getClass(), result);
|
||||
result.addAll(arguments.freeArgs);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void convertArgumentsToStringList(
|
||||
@NotNull CommonCompilerArguments arguments,
|
||||
@NotNull CommonCompilerArguments defaultArguments,
|
||||
@NotNull Class<?> clazz,
|
||||
@NotNull List<String> result
|
||||
) throws IllegalAccessException, InstantiationException {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
Argument argument = field.getAnnotation(Argument.class);
|
||||
if (argument == null) continue;
|
||||
|
||||
Object value;
|
||||
Object defaultValue;
|
||||
try {
|
||||
value = field.get(arguments);
|
||||
defaultValue = field.get(defaultArguments);
|
||||
}
|
||||
catch (IllegalAccessException ignored) {
|
||||
// skip this field
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ComparatorUtil.equalsNullable(value, defaultValue)) continue;
|
||||
|
||||
String name = getAlias(argument);
|
||||
if (name == null) {
|
||||
name = getName(argument, field);
|
||||
}
|
||||
|
||||
Class<?> fieldType = field.getType();
|
||||
|
||||
if (fieldType.isArray()) {
|
||||
Object[] values = (Object[]) value;
|
||||
if (values.length == 0) continue;
|
||||
//noinspection unchecked
|
||||
value = StringUtil.join(values, Function.TO_STRING, argument.delimiter());
|
||||
}
|
||||
|
||||
result.add(argument.prefix() + name);
|
||||
|
||||
if (fieldType == boolean.class || fieldType == Boolean.class) continue;
|
||||
|
||||
result.add(value.toString());
|
||||
}
|
||||
|
||||
Class<?> superClazz = clazz.getSuperclass();
|
||||
if (superClazz != null) {
|
||||
convertArgumentsToStringList(arguments, defaultArguments, superClazz, result);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getAlias(Argument argument) {
|
||||
String alias = argument.alias();
|
||||
return alias.isEmpty() ? null : alias;
|
||||
}
|
||||
|
||||
private static String getName(Argument argument, Field field) {
|
||||
String name = argument.value();
|
||||
return name.isEmpty() ? field.getName() : name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.config.Services;
|
||||
import org.jetbrains.kotlin.preloading.ClassCondition;
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||
import org.jetbrains.kotlin.utils.PathUtil;
|
||||
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
|
||||
|
||||
public class CompilerEnvironment {
|
||||
@NotNull
|
||||
public static CompilerEnvironment getEnvironmentFor(
|
||||
@NotNull KotlinPaths kotlinPaths,
|
||||
@NotNull ClassCondition classesToLoadByParent,
|
||||
@NotNull Services compilerServices
|
||||
) {
|
||||
return new CompilerEnvironment(kotlinPaths, classesToLoadByParent, compilerServices);
|
||||
}
|
||||
|
||||
private final KotlinPaths kotlinPaths;
|
||||
private final ClassCondition classesToLoadByParent;
|
||||
private final Services services;
|
||||
|
||||
private CompilerEnvironment(
|
||||
@NotNull KotlinPaths kotlinPaths,
|
||||
@NotNull ClassCondition classesToLoadByParent,
|
||||
@NotNull Services services
|
||||
) {
|
||||
this.kotlinPaths = kotlinPaths;
|
||||
this.classesToLoadByParent = classesToLoadByParent;
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public boolean success() {
|
||||
return kotlinPaths.getHomePath().exists();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KotlinPaths getKotlinPaths() {
|
||||
return kotlinPaths;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassCondition getClassesToLoadByParent() {
|
||||
return classesToLoadByParent;
|
||||
}
|
||||
|
||||
public void reportErrorsTo(@NotNull MessageCollector messageCollector) {
|
||||
if (!kotlinPaths.getHomePath().exists()) {
|
||||
messageCollector.report(ERROR, "Cannot find kotlinc home: " + kotlinPaths.getHomePath() + ". Make sure plugin is properly installed, " +
|
||||
"or specify " + PathUtil.JPS_KOTLIN_HOME_PROPERTY + " system property", NO_LOCATION);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Services getServices() {
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation;
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil.reportException;
|
||||
|
||||
public class CompilerOutputParser {
|
||||
public static void parseCompilerMessagesFromReader(MessageCollector messageCollector, final Reader reader, OutputItemsCollector collector) {
|
||||
// Sometimes the compiler doesn't output valid XML.
|
||||
// Example: error in command line arguments passed to the compiler.
|
||||
// The compiler will print the usage and the SAX parser will break.
|
||||
// In this case, we want to read everything from this stream and report it as an IDE error.
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
Reader wrappingReader = new Reader() {
|
||||
@Override
|
||||
public int read(@NotNull char[] cbuf, int off, int len) throws IOException {
|
||||
int read = reader.read(cbuf, off, len);
|
||||
stringBuilder.append(cbuf, off, len);
|
||||
return read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// Do nothing:
|
||||
// If the SAX parser sees a syntax error, it throws an exception
|
||||
// and calls close() on the reader.
|
||||
// We prevent hte reader from being closed here, and close it later,
|
||||
// when all the text is read from it
|
||||
}
|
||||
};
|
||||
try {
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
SAXParser parser = factory.newSAXParser();
|
||||
parser.parse(new InputSource(wrappingReader), new CompilerOutputSAXHandler(messageCollector, collector));
|
||||
}
|
||||
catch (Throwable e) {
|
||||
// Load all the text into the stringBuilder
|
||||
try {
|
||||
// This will not close the reader (see the wrapper above)
|
||||
FileUtil.loadTextAndClose(wrappingReader);
|
||||
}
|
||||
catch (IOException ioException) {
|
||||
reportException(messageCollector, ioException);
|
||||
}
|
||||
String message = stringBuilder.toString();
|
||||
reportException(messageCollector, new IllegalStateException(message, e));
|
||||
messageCollector.report(ERROR, message, NO_LOCATION);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
reader.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
reportException(messageCollector, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class CompilerOutputSAXHandler extends DefaultHandler {
|
||||
private static final Map<String, CompilerMessageSeverity> CATEGORIES = new ContainerUtil.ImmutableMapBuilder<String, CompilerMessageSeverity>()
|
||||
.put("error", ERROR)
|
||||
.put("warning", WARNING)
|
||||
.put("logging", LOGGING)
|
||||
.put("output", OUTPUT)
|
||||
.put("exception", EXCEPTION)
|
||||
.put("info", INFO)
|
||||
.put("messages", INFO) // Root XML element
|
||||
.build();
|
||||
|
||||
private final MessageCollector messageCollector;
|
||||
private final OutputItemsCollector collector;
|
||||
|
||||
private final StringBuilder message = new StringBuilder();
|
||||
private final Stack<String> tags = new Stack<String>();
|
||||
private String path;
|
||||
private int line;
|
||||
private int column;
|
||||
|
||||
public CompilerOutputSAXHandler(MessageCollector messageCollector, OutputItemsCollector collector) {
|
||||
this.messageCollector = messageCollector;
|
||||
this.collector = collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(@NotNull String uri, @NotNull String localName, @NotNull String qName, @NotNull Attributes attributes)
|
||||
throws SAXException {
|
||||
tags.push(qName);
|
||||
|
||||
message.setLength(0);
|
||||
|
||||
path = attributes.getValue("path");
|
||||
line = safeParseInt(attributes.getValue("line"), -1);
|
||||
column = safeParseInt(attributes.getValue("column"), -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
if (tags.size() == 1) {
|
||||
// We're directly inside the root tag: <MESSAGES>
|
||||
String message = new String(ch, start, length);
|
||||
if (!message.trim().isEmpty()) {
|
||||
messageCollector.report(ERROR, "Unhandled compiler output: " + message, NO_LOCATION);
|
||||
}
|
||||
}
|
||||
else {
|
||||
message.append(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, @NotNull String localName, @NotNull String qName) throws SAXException {
|
||||
if (tags.size() == 1) {
|
||||
// We're directly inside the root tag: <MESSAGES>
|
||||
return;
|
||||
}
|
||||
String qNameLowerCase = qName.toLowerCase();
|
||||
CompilerMessageSeverity category = CATEGORIES.get(qNameLowerCase);
|
||||
if (category == null) {
|
||||
messageCollector.report(ERROR, "Unknown compiler message tag: " + qName, NO_LOCATION);
|
||||
category = INFO;
|
||||
}
|
||||
String text = message.toString();
|
||||
|
||||
if (category == OUTPUT) {
|
||||
reportToCollector(text);
|
||||
}
|
||||
else {
|
||||
messageCollector.report(category, text, CompilerMessageLocation.create(path, line, column));
|
||||
}
|
||||
tags.pop();
|
||||
}
|
||||
|
||||
private void reportToCollector(String text) {
|
||||
OutputMessageUtil.Output output = OutputMessageUtil.parseOutputMessage(text);
|
||||
if (output != null) {
|
||||
collector.add(output.sourceFiles, output.outputFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static int safeParseInt(@Nullable String value, int defaultValue) {
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(value.trim());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils;
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
|
||||
|
||||
public class CompilerRunnerUtil {
|
||||
|
||||
private static SoftReference<ClassLoader> ourClassLoaderRef = new SoftReference<ClassLoader>(null);
|
||||
|
||||
@NotNull
|
||||
private static synchronized ClassLoader getOrCreateClassLoader(
|
||||
@NotNull CompilerEnvironment environment,
|
||||
@NotNull File libPath
|
||||
) throws IOException {
|
||||
ClassLoader classLoader = ourClassLoaderRef.get();
|
||||
if (classLoader == null) {
|
||||
classLoader = ClassPreloadingUtils.preloadClasses(
|
||||
Collections.singletonList(new File(libPath, "kotlin-compiler.jar")),
|
||||
/* estimatedClassNumber = */ 4096,
|
||||
CompilerRunnerUtil.class.getClassLoader(),
|
||||
environment.getClassesToLoadByParent()
|
||||
);
|
||||
ourClassLoaderRef = new SoftReference<ClassLoader>(classLoader);
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File getLibPath(@NotNull KotlinPaths paths, @NotNull MessageCollector messageCollector) {
|
||||
File libs = paths.getLibPath();
|
||||
if (libs.exists() && !libs.isFile()) return libs;
|
||||
|
||||
messageCollector.report(
|
||||
ERROR,
|
||||
"Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed",
|
||||
NO_LOCATION
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Object invokeExecMethod(
|
||||
@NotNull String compilerClassName,
|
||||
@NotNull String[] arguments,
|
||||
@NotNull CompilerEnvironment environment,
|
||||
@NotNull MessageCollector messageCollector,
|
||||
@NotNull PrintStream out
|
||||
) throws Exception {
|
||||
File libPath = getLibPath(environment.getKotlinPaths(), messageCollector);
|
||||
if (libPath == null) return null;
|
||||
|
||||
ClassLoader classLoader = getOrCreateClassLoader(environment, libPath);
|
||||
|
||||
Class<?> kompiler = Class.forName(compilerClassName, true, classLoader);
|
||||
Method exec = kompiler.getMethod(
|
||||
"execAndOutputXml",
|
||||
PrintStream.class,
|
||||
Class.forName("org.jetbrains.kotlin.config.Services", true, classLoader),
|
||||
String[].class
|
||||
);
|
||||
|
||||
return exec.invoke(kompiler.newInstance(), out, environment.getServices(), arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.Accessor;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil;
|
||||
import org.jetbrains.kotlin.config.CompilerSettings;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO;
|
||||
|
||||
public class KotlinCompilerRunner {
|
||||
private static final String K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler";
|
||||
private static final String K2JS_COMPILER = "org.jetbrains.kotlin.cli.js.K2JSCompiler";
|
||||
private static final String INTERNAL_ERROR = ExitCode.INTERNAL_ERROR.toString();
|
||||
|
||||
public static void runK2JvmCompiler(
|
||||
CommonCompilerArguments commonArguments,
|
||||
K2JVMCompilerArguments k2jvmArguments,
|
||||
CompilerSettings compilerSettings,
|
||||
MessageCollector messageCollector,
|
||||
CompilerEnvironment environment,
|
||||
File moduleFile,
|
||||
OutputItemsCollector collector
|
||||
) {
|
||||
K2JVMCompilerArguments arguments = mergeBeans(commonArguments, k2jvmArguments);
|
||||
setupK2JvmArguments(moduleFile, arguments);
|
||||
|
||||
runCompiler(K2JVM_COMPILER, arguments, compilerSettings.getAdditionalArguments(), messageCollector, collector, environment);
|
||||
}
|
||||
|
||||
public static void runK2JsCompiler(
|
||||
CommonCompilerArguments commonArguments,
|
||||
K2JSCompilerArguments k2jsArguments,
|
||||
CompilerSettings compilerSettings,
|
||||
MessageCollector messageCollector,
|
||||
CompilerEnvironment environment,
|
||||
OutputItemsCollector collector,
|
||||
Collection<File> sourceFiles,
|
||||
List<String> libraryFiles,
|
||||
File outputFile
|
||||
) {
|
||||
K2JSCompilerArguments arguments = mergeBeans(commonArguments, k2jsArguments);
|
||||
setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments);
|
||||
|
||||
runCompiler(K2JS_COMPILER, arguments, compilerSettings.getAdditionalArguments(), messageCollector, collector, environment);
|
||||
}
|
||||
|
||||
private static void runCompiler(
|
||||
String compilerClassName,
|
||||
CommonCompilerArguments arguments,
|
||||
String additionalArguments,
|
||||
MessageCollector messageCollector,
|
||||
OutputItemsCollector collector,
|
||||
CompilerEnvironment environment
|
||||
) {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
PrintStream out = new PrintStream(stream);
|
||||
|
||||
String exitCode = execCompiler(compilerClassName, arguments, additionalArguments, environment, out, messageCollector);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new StringReader(stream.toString()));
|
||||
CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader, collector);
|
||||
|
||||
if (INTERNAL_ERROR.equals(exitCode)) {
|
||||
messageCollector.report(ERROR, "Compiler terminated with internal error", NO_LOCATION);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String execCompiler(
|
||||
String compilerClassName,
|
||||
CommonCompilerArguments arguments,
|
||||
String additionalArguments,
|
||||
CompilerEnvironment environment,
|
||||
PrintStream out,
|
||||
MessageCollector messageCollector
|
||||
) {
|
||||
try {
|
||||
messageCollector.report(INFO, "Using kotlin-home = " + environment.getKotlinPaths().getHomePath(), NO_LOCATION);
|
||||
|
||||
List<String> argumentsList = ArgumentUtils.convertArgumentsToStringList(arguments);
|
||||
argumentsList.addAll(StringUtil.split(additionalArguments, " "));
|
||||
|
||||
Object rc = CompilerRunnerUtil.invokeExecMethod(
|
||||
compilerClassName, ArrayUtil.toStringArray(argumentsList), environment, messageCollector, out
|
||||
);
|
||||
|
||||
// exec() returns an ExitCode object, class of which is loaded with a different class loader,
|
||||
// so we take it's contents through reflection
|
||||
return getReturnCodeFromObject(rc);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
MessageCollectorUtil.reportException(messageCollector, e);
|
||||
return INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getReturnCodeFromObject(@Nullable Object rc) throws Exception {
|
||||
if (rc == null) {
|
||||
return INTERNAL_ERROR;
|
||||
}
|
||||
else if (ExitCode.class.getName().equals(rc.getClass().getName())) {
|
||||
return rc.toString();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unexpected return: " + rc);
|
||||
}
|
||||
}
|
||||
|
||||
private static <F, T extends F> T mergeBeans(F from, T to) {
|
||||
T copy = XmlSerializerUtil.createCopy(to);
|
||||
|
||||
for (Accessor accessor : XmlSerializerUtil.getAccessors(from.getClass())) {
|
||||
accessor.write(copy, accessor.read(from));
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
private static void setupK2JvmArguments(File moduleFile, K2JVMCompilerArguments settings) {
|
||||
settings.module = moduleFile.getAbsolutePath();
|
||||
settings.noStdlib = true;
|
||||
settings.noJdkAnnotations = true;
|
||||
settings.noJdk = true;
|
||||
}
|
||||
|
||||
private static void setupK2JsArguments(
|
||||
File outputFile,
|
||||
Collection<File> sourceFiles,
|
||||
List<String> libraryFiles,
|
||||
K2JSCompilerArguments settings
|
||||
) {
|
||||
settings.noStdlib = true;
|
||||
settings.freeArgs = ContainerUtil.map(sourceFiles, new Function<File, String>() {
|
||||
@Override
|
||||
public String fun(File file) {
|
||||
return file.getPath();
|
||||
}
|
||||
});
|
||||
settings.outputFile = outputFile.getPath();
|
||||
settings.libraryFiles = ArrayUtil.toStringArray(libraryFiles);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface OutputItemsCollector {
|
||||
void add(Collection<File> sourceFiles, File outputFile);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class OutputItemsCollectorImpl implements OutputItemsCollector {
|
||||
private final List<SimpleOutputItem> outputs = ContainerUtil.newArrayList();
|
||||
|
||||
@Override
|
||||
public void add(Collection<File> sourceFiles, File outputFile) {
|
||||
outputs.add(new SimpleOutputItem(sourceFiles, outputFile));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<SimpleOutputItem> getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.compilerRunner;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
public class SimpleOutputItem {
|
||||
private final Collection<File> sourceFiles;
|
||||
private final File outputFile;
|
||||
|
||||
public SimpleOutputItem(@NotNull Collection<File> sourceFiles, @NotNull File outputFile) {
|
||||
this.sourceFiles = sourceFiles;
|
||||
this.outputFile = outputFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<File> getSourceFiles() {
|
||||
return sourceFiles;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public File getOutputFile() {
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sourceFiles + " -> " + outputFile;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.compilerRunner.CompilerEnvironment
|
||||
import org.jetbrains.kotlin.compilerRunner.CompilerRunnerConstants
|
||||
import org.jetbrains.kotlin.config.CompilerRunnerConstants
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
@@ -43,7 +43,7 @@ import java.io.File
|
||||
import java.util.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.NO_LOCATION
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.compilerRunner.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
|
||||
import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runK2JsCompiler
|
||||
import org.jetbrains.kotlin.compilerRunner.KotlinCompilerRunner.runK2JvmCompiler
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.modules;
|
||||
|
||||
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,
|
||||
List<File> sourceFiles,
|
||||
List<File> javaSourceRoots,
|
||||
Collection<File> classpathRoots,
|
||||
List<File> annotationRoots,
|
||||
boolean tests,
|
||||
Set<File> directoriesToFilterOut
|
||||
);
|
||||
|
||||
CharSequence asText();
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.modules;
|
||||
|
||||
public interface KotlinModuleDescriptionBuilderFactory {
|
||||
KotlinModuleDescriptionBuilder create();
|
||||
String getFileExtension();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.modules;
|
||||
|
||||
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,
|
||||
List<File> sourceFiles,
|
||||
List<File> javaSourceRoots,
|
||||
Collection<File> classpathRoots,
|
||||
List<File> annotationRoots,
|
||||
boolean tests,
|
||||
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");
|
||||
}
|
||||
|
||||
if (!javaSourceRoots.isEmpty()) {
|
||||
processClassPathSection("Java source roots", javaSourceRoots, directoriesToFilterOut);
|
||||
}
|
||||
|
||||
processClassPathSection("Classpath", classpathRoots, directoriesToFilterOut);
|
||||
processAnnotationRoots(annotationRoots);
|
||||
|
||||
script.append(" }\n");
|
||||
return this;
|
||||
}
|
||||
|
||||
private void processClassPathSection(
|
||||
@NotNull String sectionDescription,
|
||||
@NotNull Collection<File> files,
|
||||
@NotNull Set<File> directoriesToFilterOut
|
||||
) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
private void processAnnotationRoots(@NotNull List<File> files) {
|
||||
script.append(" // External annotations\n");
|
||||
for (File file : files) {
|
||||
script.append(" annotationsPath += \"").append(toSystemIndependentName(file.getPath())).append("\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence asText() {
|
||||
if (!done) {
|
||||
script.append("}\n");
|
||||
done = true;
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.modules;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation;
|
||||
import org.jetbrains.kotlin.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.kotlin.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;
|
||||
|
||||
public Builder() {
|
||||
openTag(p, MODULES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KotlinModuleDescriptionBuilder addModule(
|
||||
String moduleName,
|
||||
String outputDir,
|
||||
List<File> sourceFiles,
|
||||
List<File> javaSourceRoots,
|
||||
Collection<File> classpathRoots,
|
||||
List<File> annotationRoots,
|
||||
boolean tests,
|
||||
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), "\"/>");
|
||||
}
|
||||
|
||||
if (!javaSourceRoots.isEmpty()) {
|
||||
processClassPathSection("Java source roots", javaSourceRoots, directoriesToFilterOut);
|
||||
}
|
||||
|
||||
processClassPathSection("Classpath", classpathRoots, directoriesToFilterOut);
|
||||
processAnnotationRoots(annotationRoots);
|
||||
|
||||
closeTag(p, MODULE);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void processClassPathSection(
|
||||
@NotNull String sectionDescription,
|
||||
@NotNull Collection<File> files,
|
||||
@NotNull Set<File> directoriesToFilterOut
|
||||
) {
|
||||
p.println("<!-- ", sectionDescription, " -->");
|
||||
for (File file : files) {
|
||||
boolean isOutput = directoriesToFilterOut.contains(file) && !IncrementalCompilation.ENABLED;
|
||||
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("-->");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processAnnotationRoots(@NotNull List<File> files) {
|
||||
p.println("<!-- External annotations -->");
|
||||
for (File file : files) {
|
||||
p.println("<", EXTERNAL_ANNOTATIONS, " ", PATH, "=\"", getEscapedPath(file), "\"/>");
|
||||
}
|
||||
}
|
||||
|
||||
@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()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.jvm.compiler
|
||||
|
||||
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
|
||||
import org.jetbrains.kotlin.test.JetTestUtils
|
||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||
import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilderFactory
|
||||
import java.io.File
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
|
||||
/**
|
||||
* This test checks that Java classes from sources have higher priority in Kotlin resolution process than classes from binaries.
|
||||
* To test this, we compile a Kotlin+Java module (in two modes: CLI and module-based) where a runtime Java class was replaced
|
||||
* with a "newer" version in sources, and check that this class resolves to the one from sources by calling a method absent in the runtime
|
||||
*/
|
||||
public class ClasspathOrderTest : TestCaseWithTmpdir() {
|
||||
class object {
|
||||
val sourceDir = File(JetTestUtils.getTestDataPathBase() + "/classpathOrder").getAbsoluteFile()
|
||||
}
|
||||
|
||||
public fun testClasspathOrderForCLI() {
|
||||
MockLibraryUtil.compileKotlin(sourceDir.getPath(), tmpdir)
|
||||
}
|
||||
|
||||
public fun testClasspathOrderForModuleScriptBuild() {
|
||||
val xmlContent = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule(
|
||||
"name",
|
||||
File(tmpdir, "output").getAbsolutePath(),
|
||||
listOf(sourceDir),
|
||||
listOf(sourceDir),
|
||||
listOf(PathUtil.getKotlinPathsForDistDirectory().getRuntimePath()),
|
||||
listOf(),
|
||||
false,
|
||||
setOf()
|
||||
).asText().toString()
|
||||
|
||||
val xml = File(tmpdir, "module.xml")
|
||||
xml.writeText(xmlContent)
|
||||
|
||||
MockLibraryUtil.compileKotlinModule(xml.getAbsolutePath())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.modules;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.kotlin.test.JetTestUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class KotlinModuleXmlGeneratorTest extends TestCase {
|
||||
public void testBasic() throws Exception {
|
||||
String actual = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule(
|
||||
"name",
|
||||
"output",
|
||||
Arrays.asList(new File("s1"), new File("s2")),
|
||||
Collections.singletonList(new File("java")),
|
||||
Arrays.asList(new File("cp1"), new File("cp2")),
|
||||
Arrays.asList(new File("a1/f1"), new File("a2")),
|
||||
false,
|
||||
Collections.<File>emptySet()
|
||||
).asText().toString();
|
||||
JetTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/basic.xml"), actual);
|
||||
}
|
||||
|
||||
public void testFiltered() throws Exception {
|
||||
String actual = KotlinModuleXmlBuilderFactory.INSTANCE.create().addModule(
|
||||
"name",
|
||||
"output",
|
||||
Arrays.asList(new File("s1"), new File("s2")),
|
||||
Collections.<File>emptyList(),
|
||||
Arrays.asList(new File("cp1"), new File("cp2")),
|
||||
Arrays.asList(new File("a1/f1"), new File("a2")),
|
||||
false,
|
||||
Collections.singleton(new File("cp1"))
|
||||
).asText().toString();
|
||||
JetTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/filtered.xml"), actual);
|
||||
}
|
||||
|
||||
public void testMultiple() throws Exception {
|
||||
KotlinModuleDescriptionBuilder builder = KotlinModuleXmlBuilderFactory.INSTANCE.create();
|
||||
builder.addModule(
|
||||
"name",
|
||||
"output",
|
||||
Arrays.asList(new File("s1"), new File("s2")),
|
||||
Collections.<File>emptyList(),
|
||||
Arrays.asList(new File("cp1"), new File("cp2")),
|
||||
Arrays.asList(new File("a1/f1"), new File("a2")),
|
||||
false,
|
||||
Collections.singleton(new File("cp1"))
|
||||
);
|
||||
builder.addModule(
|
||||
"name2",
|
||||
"output2",
|
||||
Arrays.asList(new File("s12"), new File("s22")),
|
||||
Collections.<File>emptyList(),
|
||||
Arrays.asList(new File("cp12"), new File("cp22")),
|
||||
Arrays.asList(new File("a12/f12"), new File("a22")),
|
||||
true,
|
||||
Collections.singleton(new File("cp12"))
|
||||
);
|
||||
String actual = builder.asText().toString();
|
||||
JetTestUtils.assertEqualsToFile(new File("idea/testData/modules.xml/multiple.xml"), actual);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user