Added support project settings in old kotlin2js compiler and made minor refactoring.

This commit is contained in:
Zalim Bashorov
2013-10-16 16:04:24 +04:00
parent fb8c9c2ef9
commit 5a28f4e158
11 changed files with 92 additions and 139 deletions
@@ -16,6 +16,8 @@
package com.sampullara.cli;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ComparatorUtil;
import org.jetbrains.annotations.NotNull;
@@ -66,12 +68,19 @@ public class ArgumentUtils {
name = Args.getName(argument, field);
}
Class<?> fieldType = field.getType();
if (fieldType.isArray()) {
Object[] values = (Object[]) value;
if (values.length == 0) continue;
value = StringUtil.join(values, Function.TO_STRING, argument.delimiter());
}
result.add(argument.prefix() + name);
Class<?> fieldType = field.getType();
if (fieldType != boolean.class && fieldType != Boolean.class) {
result.add(value.toString());
}
if (fieldType == boolean.class || fieldType == Boolean.class) continue;
result.add(value.toString());
}
}
@@ -189,14 +189,14 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
@NotNull MessageRenderer messageRenderer
) {
if (arguments.printArgs) {
String freeArgs = StringUtil.join(arguments.freeArgs, " ");
String freeArgs = !arguments.freeArgs.isEmpty() ? " " + StringUtil.join(arguments.freeArgs, " ") : "";
List<String> argumentsAsList = ArgumentUtils.convertArgumentsToStringList(arguments, createArguments());
String argumentsAsString = StringUtil.join(argumentsAsList, " ");
String printArgsMessage = messageRenderer.render(CompilerMessageSeverity.INFO,
"Invoking compiler " + getClass().getName() +
" with arguments " + argumentsAsString + " " + freeArgs,
" with arguments " + argumentsAsString + freeArgs,
CompilerMessageLocation.NO_LOCATION);
errStream.println(printArgsMessage);
}
@@ -93,17 +93,17 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
reportCompiledSourcesList(messageCollector, environmentForJS);
}
Config config = getConfig(arguments, project);
if (analyzeAndReportErrors(messageCollector, environmentForJS.getSourceFiles(), config)) {
return COMPILATION_ERROR;
}
String outputFile = arguments.outputFile;
if (outputFile == null) {
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify output file via -output", CompilerMessageLocation.NO_LOCATION);
return ExitCode.INTERNAL_ERROR;
}
Config config = getConfig(arguments, project);
if (analyzeAndReportErrors(messageCollector, environmentForJS.getSourceFiles(), config)) {
return COMPILATION_ERROR;
}
MainCallParameters mainCallParameters = createMainCallParameters(arguments.main);
return translateAndGenerateOutputFile(mainCallParameters, environmentForJS, config, outputFile);
}
@@ -0,0 +1,3 @@
INFO: Invoking compiler org.jetbrains.jet.cli.js.K2JSCompiler with arguments -suppress warnings -printArgs -sourceFiles compiler/testData/cli/simple2js.kt,compiler/testData/cli/warnings.kt
ERROR: Specify output file via -output
COMPILATION_ERROR
+1
View File
@@ -0,0 +1 @@
fun main(args: Array<String>) {}
@@ -201,6 +201,14 @@ public class CliTest {
executeCompilerCompareOutputJVM(new String[] {"-printArgs", "-script", "compiler/testData/cli/hello.ktscript"});
}
@Test
public void printArgumentsWithManyValue() {
executeCompilerCompareOutputJS(new String[] {
"-printArgs",
"-sourceFiles", "compiler/testData/cli/simple2js.kt,compiler/testData/cli/warnings.kt",
"-suppress", "warnings"});
}
@Test
public void nonExistingClassPathAndAnnotationsPath() {
String[] args = {
@@ -51,7 +51,7 @@ class JSDeclarationsCacheProvider extends DeclarationsCacheProvider {
synchronized (declarationAnalysisLock) {
LibrarySourcesConfig config = new LibrarySourcesConfig(
project, "default",
KotlinFrameworkDetector.getLibLocationAndTargetForProject(project).first,
KotlinFrameworkDetector.getLibLocationForProject(project),
EcmaVersion.defaultVersion(), false);
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJS.analyzeFiles(
@@ -16,43 +16,36 @@
package org.jetbrains.jet.plugin.compiler;
import com.google.common.collect.Lists;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
import com.intellij.util.Function;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.jet.cli.common.arguments.K2JSCompilerArguments;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.compiler.runner.CompilerEnvironment;
import org.jetbrains.jet.compiler.runner.CompilerRunnerUtil;
import org.jetbrains.jet.compiler.runner.KotlinCompilerRunner;
import org.jetbrains.jet.compiler.runner.OutputItemsCollectorImpl;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.compiler.configuration.Kotlin2JsCompilerSettings;
import org.jetbrains.jet.plugin.compiler.configuration.KotlinCommonCompilerSettings;
import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector;
import java.io.File;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.compiler.runner.CompilerRunnerUtil.invokeExecMethod;
import static org.jetbrains.jet.compiler.runner.CompilerRunnerUtil.outputCompilerMessagesAndHandleExitCode;
public final class K2JSCompiler implements TranslatingCompiler {
@Override
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
@@ -85,19 +78,38 @@ public final class K2JSCompiler implements TranslatingCompiler {
return;
}
doCompile(messageCollector, sink, module, environment);
doCompile(messageCollector, sink, module, environment, files);
}
private static void doCompile(@NotNull final MessageCollector messageCollector, @NotNull OutputSink sink, @NotNull final Module module,
@NotNull final CompilerEnvironment environment) {
OutputItemsCollectorImpl collector = new OutputItemsCollectorImpl();
outputCompilerMessagesAndHandleExitCode(messageCollector, collector, new Function<PrintStream, Integer>() {
private static void doCompile(
@NotNull MessageCollector messageCollector, @NotNull OutputSink sink, @NotNull Module module,
@NotNull CompilerEnvironment environment, VirtualFile[] files
) {
List<File> srcFiles = ContainerUtil.map(files, new Function<VirtualFile, File>() {
@Override
public Integer fun(PrintStream stream) {
return execInProcess(messageCollector, environment, stream, module);
public File fun(VirtualFile file) {
return new File(file.getPath());
}
});
TranslatingCompilerUtils.reportOutputs(sink, environment.getOutput(), collector);
List<String> libraryFiles = getLibraryFiles(module);
File outDir = environment.getOutput();
File outFile = new File(outDir, module.getName() + ".js");
OutputItemsCollectorImpl outputItemsCollector = new OutputItemsCollectorImpl();
CommonCompilerArguments commonArguments = KotlinCommonCompilerSettings.getInstance(module.getProject()).getSettings();
K2JSCompilerArguments k2jsArguments = Kotlin2JsCompilerSettings.getInstance(module.getProject()).getSettings();
KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2jsArguments, messageCollector, environment,
outputItemsCollector, srcFiles, libraryFiles, outFile);
if (!ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(outDir);
assert virtualFile != null : "Virtual file not found for module output: " + outDir;
virtualFile.refresh(false, true);
}
TranslatingCompilerUtils.reportOutputs(sink, environment.getOutput(), outputItemsCollector);
}
@Nullable
@@ -109,48 +121,6 @@ public final class K2JSCompiler implements TranslatingCompiler {
return moduleChunk.getNodes().iterator().next();
}
@NotNull
private static Integer execInProcess(@NotNull MessageCollector messageCollector,
@NotNull CompilerEnvironment environment, @NotNull PrintStream out, @NotNull Module module) {
try {
return doExec(messageCollector, environment, out, module);
}
catch (Throwable e) {
messageCollector.report(CompilerMessageSeverity.ERROR,
"Exception while executing compiler:\n" + e.getMessage(),
CompilerMessageLocation.NO_LOCATION);
}
return -1;
}
@NotNull
private static Integer doExec(@NotNull MessageCollector messageCollector, @NotNull CompilerEnvironment environment, @NotNull PrintStream out,
@NotNull Module module) throws Exception {
File outDir = environment.getOutput();
File outFile = new File(outDir, module.getName() + ".js");
String[] commandLineArgs = constructArguments(module, outFile);
// No preloading for in-process compiler
Object rc = invokeExecMethod("org.jetbrains.jet.cli.js.K2JSCompiler", commandLineArgs, environment, messageCollector, out, false);
if (!ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(outDir);
assert virtualFile != null : "Virtual file not found for module output: " + outDir;
virtualFile.refresh(false, true);
}
return CompilerRunnerUtil.getReturnCodeFromObject(rc);
}
@NotNull
private static String[] constructArguments(@NotNull Module module, @NotNull File outFile) {
VirtualFile[] sourceFiles = getSourceFiles(module);
ArrayList<String> args = Lists.newArrayList("-tags", "-verbose", "-version");
addPathToSourcesDir(sourceFiles, args);
addOutputPath(outFile, args);
addLibLocationAndTarget(module, args);
return ArrayUtil.toStringArray(args);
}
// we cannot use OrderEnumerator because it has critical bug - try https://gist.github.com/2953261, processor will never be called for module dependency
// we don't use context.getCompileScope().getAffectedModules() because we want to know about linkage type (well, we ignore scope right now, but in future...)
private static void collectModuleDependencies(Module dependentModule, Set<Module> modules) {
@@ -178,67 +148,28 @@ public final class K2JSCompiler implements TranslatingCompiler {
.getFiles(JetFileType.INSTANCE, true);
}
private static void addLibLocationAndTarget(@NotNull Module module, @NotNull ArrayList<String> args) {
Pair<List<String>, String> libLocationAndTarget = KotlinFrameworkDetector.getLibLocationAndTargetForProject(module);
private static List<String> getLibraryFiles(@NotNull Module module) {
List<String> result = new ArrayList<String>();
StringBuilder sb = StringBuilderSpinAllocator.alloc();
AccessToken token = ReadAction.start();
try {
THashSet<Module> modules = new THashSet<Module>();
collectModuleDependencies(module, modules);
if (!modules.isEmpty()) {
for (Module dependency : modules) {
sb.append('@').append(dependency.getName()).append(',');
List<String> libLocationAndTarget = KotlinFrameworkDetector.getLibLocationForProject(module);
for (VirtualFile file : getSourceFiles(dependency)) {
sb.append(file.getPath()).append(',');
}
THashSet<Module> modules = new THashSet<Module>();
collectModuleDependencies(module, modules);
if (!modules.isEmpty()) {
for (Module dependency : modules) {
result.add("@" + dependency.getName());
for (VirtualFile file : getSourceFiles(dependency)) {
result.add(file.getPath());
}
}
if (libLocationAndTarget.first != null) {
for (String file : libLocationAndTarget.first) {
sb.append(file).append(',');
}
}
if (sb.length() > 0) {
args.add("-libraryFiles");
args.add(sb.substring(0, sb.length() - 1));
}
}
finally {
token.finish();
StringBuilderSpinAllocator.dispose(sb);
}
if (libLocationAndTarget.second != null) {
args.add("-target");
args.add(libLocationAndTarget.second);
for (String file : libLocationAndTarget) {
result.add(file);
}
//TODO drop later
args.add("-sourcemap");
}
private static void addPathToSourcesDir(@NotNull VirtualFile[] sourceFiles, @NotNull ArrayList<String> args) {
args.add("-sourceFiles");
StringBuilder sb = StringBuilderSpinAllocator.alloc();
try {
for (VirtualFile file : sourceFiles) {
sb.append(file.getPath()).append(',');
}
args.add(sb.substring(0, sb.length() - 1));
}
finally {
StringBuilderSpinAllocator.dispose(sb);
}
}
private static void addOutputPath(@NotNull File outFile, @NotNull ArrayList<String> args) {
args.add("-output");
args.add(outFile.getPath());
return result;
}
@NotNull
@@ -29,7 +29,6 @@ import com.intellij.openapi.roots.ProjectRootModificationTracker;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
@@ -43,8 +42,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.plugin.configuration.ConfigureKotlinInProjectUtils;
import org.jetbrains.jet.plugin.versions.KotlinRuntimeLibraryUtil;
import org.jetbrains.k2js.config.EcmaVersion;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -82,18 +81,19 @@ public class KotlinFrameworkDetector {
}
@NotNull
public static Pair<List<String>, String> getLibLocationAndTargetForProject(@NotNull Project project) {
public static List<String> getLibLocationForProject(@NotNull Project project) {
Module[] modules = ModuleManager.getInstance(project).getModules();
for (Module module : modules) {
if (isJsKotlinModule(module)) {
return getLibLocationAndTargetForProject(module);
return getLibLocationForProject(module);
}
}
return Pair.empty();
return Collections.emptyList();
}
public static Pair<List<String>, String> getLibLocationAndTargetForProject(final Module module) {
@NotNull
public static List<String> getLibLocationForProject(@NotNull final Module module) {
final Set<String> pathsToJSLib = Sets.newHashSet();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -120,7 +120,7 @@ public class KotlinFrameworkDetector {
}
});
return Pair.<List<String>, String>create(Lists.newArrayList(pathsToJSLib), EcmaVersion.defaultVersion().toString());
return Lists.newArrayList(pathsToJSLib);
}
@@ -18,13 +18,12 @@ package org.jetbrains.jet.plugin.project;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.config.LibrarySourcesConfig;
import static org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector.getLibLocationAndTargetForProject;
public final class IDEAConfig extends LibrarySourcesConfig {
public IDEAConfig(@NotNull Project project) {
super(project, "default", getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion(), false);
super(project, "default", KotlinFrameworkDetector.getLibLocationForProject(project), EcmaVersion.defaultVersion(), false);
}
}
@@ -100,7 +100,9 @@ public final class K2JSCompilerMessagingTest extends IDECompilerMessagingTest {
@Override
protected void checkHeader(@NotNull MessageChecker checker) {
checker.expect(Message.info().textStartsWith("Kotlin Compiler version"));
checker.expect(info().textStartsWith("Using kotlinHome="));
checker.expect(info().textStartsWith("Invoking compiler"));
checker.expect(info().textStartsWith("Kotlin Compiler version"));
checker.expect(stats().textMatchesRegexp("Compiling source files: .*/src/test.kt"));
}
}