001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.jet.cli.js; 018 019import com.google.common.base.Function; 020import com.google.common.base.Joiner; 021import com.google.common.base.Predicates; 022import com.google.common.collect.Iterables; 023import com.intellij.openapi.Disposable; 024import com.intellij.openapi.project.Project; 025import com.intellij.openapi.util.io.FileUtil; 026import com.intellij.openapi.vfs.VirtualFile; 027import com.intellij.psi.PsiFile; 028import jet.Function0; 029import org.jetbrains.annotations.NotNull; 030import org.jetbrains.annotations.Nullable; 031import org.jetbrains.jet.analyzer.AnalyzeExhaust; 032import org.jetbrains.jet.cli.common.CLICompiler; 033import org.jetbrains.jet.cli.common.ExitCode; 034import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport; 035import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation; 036import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity; 037import org.jetbrains.jet.cli.common.messages.MessageCollector; 038import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; 039import org.jetbrains.jet.config.CommonConfigurationKeys; 040import org.jetbrains.jet.config.CompilerConfiguration; 041import org.jetbrains.jet.lang.psi.JetFile; 042import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS; 043import org.jetbrains.k2js.config.*; 044import org.jetbrains.k2js.facade.K2JSTranslator; 045import org.jetbrains.k2js.facade.MainCallParameters; 046 047import java.io.File; 048import java.util.Arrays; 049import java.util.List; 050 051import static org.jetbrains.jet.cli.common.ExitCode.COMPILATION_ERROR; 052import static org.jetbrains.jet.cli.common.ExitCode.OK; 053import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION; 054 055public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> { 056 057 public static void main(String... args) { 058 doMain(new K2JSCompiler(), args); 059 } 060 061 @NotNull 062 @Override 063 protected K2JSCompilerArguments createArguments() { 064 return new K2JSCompilerArguments(); 065 } 066 067 068 @NotNull 069 @Override 070 protected ExitCode doExecute(K2JSCompilerArguments arguments, MessageCollector messageCollector, Disposable rootDisposable) { 071 if (arguments.sourceFiles == null) { 072 messageCollector.report(CompilerMessageSeverity.ERROR, "Specify sources location via -sourceFiles", NO_LOCATION); 073 return ExitCode.INTERNAL_ERROR; 074 } 075 076 CompilerConfiguration configuration = new CompilerConfiguration(); 077 configuration.addAll(CommonConfigurationKeys.SOURCE_ROOTS_KEY, Arrays.asList(arguments.sourceFiles)); 078 JetCoreEnvironment environmentForJS = new JetCoreEnvironment(rootDisposable, configuration); 079 080 Project project = environmentForJS.getProject(); 081 082 ClassPathLibrarySourcesLoader sourceLoader = new ClassPathLibrarySourcesLoader(project); 083 List<JetFile> sourceFiles = sourceLoader.findSourceFiles(); 084 environmentForJS.getSourceFiles().addAll(sourceFiles); 085 086 if (arguments.isVerbose()) { 087 reportCompiledSourcesList(messageCollector, environmentForJS); 088 } 089 090 Config config = getConfig(arguments, project); 091 if (analyzeAndReportErrors(messageCollector, environmentForJS.getSourceFiles(), config)) { 092 return COMPILATION_ERROR; 093 } 094 095 String outputFile = arguments.outputFile; 096 if (outputFile == null) { 097 messageCollector.report(CompilerMessageSeverity.ERROR, "Specify output file via -output", CompilerMessageLocation.NO_LOCATION); 098 return ExitCode.INTERNAL_ERROR; 099 } 100 101 MainCallParameters mainCallParameters = arguments.createMainCallParameters(); 102 return translateAndGenerateOutputFile(mainCallParameters, environmentForJS, config, outputFile); 103 } 104 105 private static void reportCompiledSourcesList(@NotNull MessageCollector messageCollector, 106 @NotNull JetCoreEnvironment environmentForJS) { 107 List<JetFile> files = environmentForJS.getSourceFiles(); 108 Iterable<String> fileNames = Iterables.transform(files, new Function<JetFile, String>() { 109 @Override 110 public String apply(@Nullable JetFile file) { 111 assert file != null; 112 VirtualFile virtualFile = file.getVirtualFile(); 113 if (virtualFile != null) { 114 return FileUtil.toSystemIndependentName(virtualFile.getPath()); 115 } 116 return file.getName() + "(no virtual file)"; 117 } 118 }); 119 messageCollector.report(CompilerMessageSeverity.LOGGING, "Compiling source files: " + Joiner.on(", ").join(fileNames), 120 CompilerMessageLocation.NO_LOCATION); 121 } 122 123 @NotNull 124 private static ExitCode translateAndGenerateOutputFile( 125 @NotNull MainCallParameters mainCall, 126 @NotNull JetCoreEnvironment environmentForJS, 127 @NotNull Config config, 128 @NotNull String outputFile 129 ) { 130 try { 131 K2JSTranslator.translateWithMainCallParametersAndSaveToFile(mainCall, environmentForJS.getSourceFiles(), outputFile, config); 132 } 133 catch (Exception e) { 134 throw new RuntimeException(e); 135 } 136 return OK; 137 } 138 139 private static boolean analyzeAndReportErrors(@NotNull MessageCollector messageCollector, 140 @NotNull final List<JetFile> sources, @NotNull final Config config) { 141 AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(messageCollector); 142 analyzerWithCompilerReport.analyzeAndReport(new Function0<AnalyzeExhaust>() { 143 @Override 144 public AnalyzeExhaust invoke() { 145 return AnalyzerFacadeForJS.analyzeFiles(sources, Predicates.<PsiFile>alwaysTrue(), config); 146 } 147 }, sources); 148 return analyzerWithCompilerReport.hasErrors(); 149 } 150 151 @NotNull 152 private static Config getConfig(@NotNull K2JSCompilerArguments arguments, @NotNull Project project) { 153 EcmaVersion ecmaVersion = EcmaVersion.fromString(arguments.target); 154 String moduleId = FileUtil.getNameWithoutExtension(new File(arguments.outputFile)); 155 if (arguments.libraryFiles != null) { 156 return new LibrarySourcesConfig(project, moduleId, Arrays.asList(arguments.libraryFiles), ecmaVersion); 157 } 158 else { 159 // lets discover the JS library definitions on the classpath 160 return new ClassPathLibraryDefintionsConfig(project, moduleId, ecmaVersion); 161 } 162 } 163}