JS backend: check libraries in cli compiler before translation
This commit is contained in:
@@ -28,6 +28,8 @@ import com.intellij.util.Function;
|
|||||||
import com.intellij.util.SmartList;
|
import com.intellij.util.SmartList;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.Function0;
|
import kotlin.Function0;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.OutputFileCollection;
|
import org.jetbrains.jet.OutputFileCollection;
|
||||||
@@ -79,7 +81,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
protected ExitCode doExecute(
|
protected ExitCode doExecute(
|
||||||
@NotNull K2JSCompilerArguments arguments,
|
@NotNull K2JSCompilerArguments arguments,
|
||||||
@NotNull Services services,
|
@NotNull Services services,
|
||||||
@NotNull MessageCollector messageCollector,
|
@NotNull final MessageCollector messageCollector,
|
||||||
@NotNull Disposable rootDisposable
|
@NotNull Disposable rootDisposable
|
||||||
) {
|
) {
|
||||||
if (arguments.freeArgs.isEmpty()) {
|
if (arguments.freeArgs.isEmpty()) {
|
||||||
@@ -109,6 +111,16 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
File outputFile = new File(arguments.outputFile);
|
File outputFile = new File(arguments.outputFile);
|
||||||
|
|
||||||
Config config = getConfig(arguments, project);
|
Config config = getConfig(arguments, project);
|
||||||
|
if (config.checkLibFilesAndReportErrors(new Function1<String, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(String message) {
|
||||||
|
messageCollector.report(CompilerMessageSeverity.ERROR, message, CompilerMessageLocation.NO_LOCATION);
|
||||||
|
return Unit.INSTANCE$;
|
||||||
|
}
|
||||||
|
})) {
|
||||||
|
return COMPILATION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (analyzeAndReportErrors(messageCollector, sourcesFiles, config)) {
|
if (analyzeAndReportErrors(messageCollector, sourcesFiles, config)) {
|
||||||
return COMPILATION_ERROR;
|
return COMPILATION_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$TESTDATA_DIR$/withLib.kt
|
||||||
|
-library-files
|
||||||
|
not/existing/path
|
||||||
|
-output
|
||||||
|
$TEMP_DIR$/out.js
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ERROR: Path 'not/existing/path'does not exist
|
||||||
|
COMPILATION_ERROR
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$TESTDATA_DIR$/withLib.kt
|
||||||
|
-library-files
|
||||||
|
compiler/integration-tests/testData/ant/js/simpleWithStdlibAndFolderAsAnotherLib
|
||||||
|
-output
|
||||||
|
$TEMP_DIR$/out.js
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ERROR: 'compiler/integration-tests/testData/ant/js/simpleWithStdlibAndFolderAsAnotherLib' is not a valid Kotlin Javascript library
|
||||||
|
COMPILATION_ERROR
|
||||||
@@ -168,6 +168,12 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes
|
|||||||
doJsTest(fileName);
|
doJsTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("libraryDirNotFound.args")
|
||||||
|
public void testLibraryDirNotFound() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/js/libraryDirNotFound.args");
|
||||||
|
doJsTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nativeDeclarations.args")
|
@TestMetadata("nativeDeclarations.args")
|
||||||
public void testNativeDeclarations() throws Exception {
|
public void testNativeDeclarations() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/js/nativeDeclarations.args");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/js/nativeDeclarations.args");
|
||||||
@@ -180,6 +186,12 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes
|
|||||||
doJsTest(fileName);
|
doJsTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("notValidLibraryDir.args")
|
||||||
|
public void testNotValidLibraryDir() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/js/notValidLibraryDir.args");
|
||||||
|
doJsTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("outputPostfixFileNotFound.args")
|
@TestMetadata("outputPostfixFileNotFound.args")
|
||||||
public void testOutputPostfixFileNotFound() throws Exception {
|
public void testOutputPostfixFileNotFound() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/js/outputPostfixFileNotFound.args");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/js/outputPostfixFileNotFound.args");
|
||||||
|
|||||||
@@ -76,4 +76,18 @@ public class K2JsCliTest extends CliBaseTest {
|
|||||||
|
|
||||||
Assert.assertTrue(new File(tmpdir.getTmpDir(), "out.js").isFile());
|
Assert.assertTrue(new File(tmpdir.getTmpDir(), "out.js").isFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void libraryDirNotFound() throws Exception {
|
||||||
|
executeCompilerCompareOutputJS();
|
||||||
|
|
||||||
|
Assert.assertFalse(new File(tmpdir.getTmpDir(), "out.js").isFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void notValidLibraryDir() throws Exception {
|
||||||
|
executeCompilerCompareOutputJS();
|
||||||
|
|
||||||
|
Assert.assertFalse(new File(tmpdir.getTmpDir(), "out.js").isFile());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package org.jetbrains.k2js.config;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
|
||||||
@@ -82,6 +84,8 @@ public abstract class Config {
|
|||||||
return moduleId;
|
return moduleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected abstract List<JetFile> generateLibFiles();
|
protected abstract List<JetFile> generateLibFiles();
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.k2js.config;
|
package org.jetbrains.k2js.config;
|
||||||
|
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Key;
|
import com.intellij.openapi.util.Key;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
@@ -24,7 +23,11 @@ import com.intellij.openapi.vfs.*;
|
|||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.PsiManager;
|
import com.intellij.psi.PsiManager;
|
||||||
import com.intellij.util.io.URLUtil;
|
import com.intellij.util.io.URLUtil;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.Function2;
|
||||||
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
import org.jetbrains.k2js.JavaScript;
|
import org.jetbrains.k2js.JavaScript;
|
||||||
@@ -43,8 +46,6 @@ public class LibrarySourcesConfig extends Config {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>";
|
public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>";
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.k2js.config.LibrarySourcesConfig");
|
|
||||||
public static final String STDLIB_JS_MODULE_NAME = "stdlib";
|
public static final String STDLIB_JS_MODULE_NAME = "stdlib";
|
||||||
public static final String BUILTINS_JS_MODULE_NAME = "builtins";
|
public static final String BUILTINS_JS_MODULE_NAME = "builtins";
|
||||||
public static final String BUILTINS_JS_FILE_NAME = BUILTINS_JS_MODULE_NAME + JavaScript.DOT_EXTENSION;
|
public static final String BUILTINS_JS_FILE_NAME = BUILTINS_JS_MODULE_NAME + JavaScript.DOT_EXTENSION;
|
||||||
@@ -72,11 +73,44 @@ public class LibrarySourcesConfig extends Config {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<JetFile> jetFiles = new ArrayList<JetFile>();
|
final List<JetFile> jetFiles = new ArrayList<JetFile>();
|
||||||
|
final PsiManager psiManager = PsiManager.getInstance(getProject());
|
||||||
|
|
||||||
|
Function1<String, Unit> report = new Function1<String, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(String message) {
|
||||||
|
throw new IllegalStateException(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Function2<String, VirtualFile, Unit> action = new Function2<String, VirtualFile, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(String moduleName, VirtualFile file) {
|
||||||
|
JetFileCollector jetFileCollector = new JetFileCollector(jetFiles, moduleName, psiManager);
|
||||||
|
VfsUtilCore.visitChildrenRecursively(file, jetFileCollector);
|
||||||
|
return Unit.INSTANCE$;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean hasErrors = checkLibFilesAndReportErrors(report, action);
|
||||||
|
assert !hasErrors : "hasErrors should be false";
|
||||||
|
|
||||||
|
return jetFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report) {
|
||||||
|
return checkLibFilesAndReportErrors(report, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report, @Nullable Function2<String, VirtualFile, Unit> action) {
|
||||||
|
if (files.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
VirtualFileSystem fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL);
|
VirtualFileSystem fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL);
|
||||||
VirtualFileSystem jarFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JAR_PROTOCOL);
|
VirtualFileSystem jarFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JAR_PROTOCOL);
|
||||||
|
|
||||||
PsiManager psiManager = PsiManager.getInstance(getProject());
|
|
||||||
String moduleName = null;
|
String moduleName = null;
|
||||||
|
|
||||||
for (String path : files) {
|
for (String path : files) {
|
||||||
@@ -87,6 +121,12 @@ public class LibrarySourcesConfig extends Config {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File filePath = new File(path);
|
||||||
|
if (!filePath.exists()) {
|
||||||
|
report.invoke("Path '" + path + "'does not exist");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (path.endsWith(".jar") || path.endsWith(".zip")) {
|
if (path.endsWith(".jar") || path.endsWith(".zip")) {
|
||||||
file = jarFileSystem.findFileByPath(path + URLUtil.JAR_SEPARATOR);
|
file = jarFileSystem.findFileByPath(path + URLUtil.JAR_SEPARATOR);
|
||||||
}
|
}
|
||||||
@@ -95,23 +135,29 @@ public class LibrarySourcesConfig extends Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
LOG.error("File '" + path + "' not found.'");
|
report.invoke("File '" + path + "'does not exist or could not be read");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
File filePath = new File(path);
|
|
||||||
if (isKotlinJavascriptLibrary(filePath)) {
|
if (isKotlinJavascriptLibrary(filePath)) {
|
||||||
actualModuleName = LibraryUtils.getKotlinJsModuleName(filePath);
|
actualModuleName = LibraryUtils.getKotlinJsModuleName(filePath);
|
||||||
}
|
}
|
||||||
if (actualModuleName == null) {
|
else if (actualModuleName == null) {
|
||||||
LOG.error("Could not find " + LibraryUtils.KOTLIN_JS_MODULE_NAME + " for " + filePath);
|
report.invoke("'" + path + "' is not a valid Kotlin Javascript library");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (actualModuleName == null) {
|
||||||
|
report.invoke("Could not find " + LibraryUtils.KOTLIN_JS_MODULE_NAME + " for '" + path + "'");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (action != null) {
|
||||||
|
action.invoke(actualModuleName, file);
|
||||||
}
|
}
|
||||||
JetFileCollector jetFileCollector = new JetFileCollector(jetFiles, actualModuleName, psiManager);
|
|
||||||
VfsUtilCore.visitChildrenRecursively(file, jetFileCollector);
|
|
||||||
}
|
}
|
||||||
moduleName = null;
|
moduleName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return jetFiles;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JetFile getJetFileByVirtualFile(VirtualFile file, String moduleName, PsiManager psiManager) {
|
protected JetFile getJetFileByVirtualFile(VirtualFile file, String moduleName, PsiManager psiManager) {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import com.intellij.openapi.util.text.StringUtil;
|
|||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.PsiManager;
|
import com.intellij.psi.PsiManager;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.Unit;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.analyzer.AnalysisResult;
|
import org.jetbrains.jet.analyzer.AnalysisResult;
|
||||||
@@ -137,6 +139,10 @@ public class LibrarySourcesConfigWithCaching extends LibrarySourcesConfig {
|
|||||||
protected List<JetFile> generateLibFiles() {
|
protected List<JetFile> generateLibFiles() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user