Idea 138: Fix compilation after removing old make api

Tests are removed
This commit is contained in:
Nikolay Krasko
2014-06-11 18:03:29 +04:00
parent 1e3270a050
commit e925b5bdb6
13 changed files with 5 additions and 1367 deletions
@@ -17,13 +17,11 @@
package org.jetbrains.jet.plugin.compiler;
import com.intellij.diagnostic.PluginException;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -34,7 +32,6 @@ import org.jetbrains.jet.plugin.JetFileType;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Set;
import static org.jetbrains.jet.compiler.runner.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX;
@@ -48,19 +45,10 @@ public class JetCompilerManager implements ProjectComponent {
private static final Set<String> FILE_EXTS_WHICH_NEEDS_REFRESH = ContainerUtil.immutableSet(".js", ".map");
public JetCompilerManager(Project project, CompilerManager manager) {
manager.addTranslatingCompiler(new K2JvmTranslatingCompiler(),
Collections.<FileType>singleton(JetFileType.INSTANCE),
Collections.singleton(StdFileTypes.CLASS));
manager.addTranslatingCompiler(new K2JsTranslatingCompiler(),
Collections.<FileType>singleton(JetFileType.INSTANCE),
Collections.<FileType>singleton(StdFileTypes.JS));
manager.addCompilableFileType(JetFileType.INSTANCE);
manager.addCompilationStatusListener(new CompilationStatusListener() {
@Override
public void compilationFinished(
boolean aborted, int errors, int warnings, CompileContext compileContext
) {
public void compilationFinished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
for (CompilerMessage error : compileContext.getMessages(CompilerMessageCategory.ERROR)) {
String message = error.getMessage();
if (message.startsWith(INTERNAL_ERROR_PREFIX) || message.startsWith(PREFIX_WITH_COMPILER_NAME)) {
@@ -112,7 +100,7 @@ public class JetCompilerManager implements ProjectComponent {
private final String text;
public KotlinCompilerException(String text) {
super("", PluginManager.getPluginByClassName(JetCompilerManager.class.getName()));
super("", PluginManagerCore.getPluginByClassName(JetCompilerManager.class.getName()));
this.text = text;
}
@@ -122,10 +110,11 @@ public class JetCompilerManager implements ProjectComponent {
}
@Override
public void printStackTrace(PrintStream s) {
public void printStackTrace(@NotNull PrintStream s) {
s.print(text);
}
@NotNull
@Override
public synchronized Throwable fillInStackTrace() {
return this;
@@ -1,182 +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.plugin.compiler;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import com.intellij.util.Function;
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.arguments.CommonCompilerArguments;
import org.jetbrains.jet.cli.common.arguments.K2JSCompilerArguments;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.compiler.CompilerSettings;
import org.jetbrains.jet.compiler.runner.CompilerEnvironment;
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.Kotlin2JsCompilerArgumentsHolder;
import org.jetbrains.jet.plugin.compiler.configuration.KotlinCommonCompilerArgumentsHolder;
import org.jetbrains.jet.plugin.compiler.configuration.KotlinCompilerSettings;
import org.jetbrains.jet.plugin.project.ProjectStructureUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public final class K2JsTranslatingCompiler implements TranslatingCompiler {
@Override
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
if (!(file.getFileType() instanceof JetFileType)) {
return false;
}
Module module = context.getModuleByFile(file);
if (module == null) {
return false;
}
return ProjectStructureUtil.isJsKotlinModule(module);
}
@Override
public void compile(CompileContext context, Chunk<Module> moduleChunk, VirtualFile[] files, OutputSink sink) {
if (files.length == 0) {
return;
}
Module module = getModule(context, moduleChunk);
if (module == null) {
return;
}
MessageCollector messageCollector = new MessageCollectorAdapter(context);
CompilerEnvironment environment = TranslatingCompilerUtils.getEnvironmentFor(context, module, /*tests = */ false);
if (!environment.success()) {
environment.reportErrorsTo(messageCollector);
return;
}
doCompile(messageCollector, sink, module, environment, files);
}
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 File fun(VirtualFile file) {
return new File(file.getPath());
}
});
List<String> libraryFiles = getLibraryFiles(module);
File outDir = environment.getOutput();
File outFile = new File(outDir, module.getName() + ".js");
OutputItemsCollectorImpl outputItemsCollector = new OutputItemsCollectorImpl();
Project project = module.getProject();
CommonCompilerArguments commonArguments = KotlinCommonCompilerArgumentsHolder.getInstance(project).getSettings();
K2JSCompilerArguments k2jsArguments = Kotlin2JsCompilerArgumentsHolder.getInstance(project).getSettings();
CompilerSettings compilerSettings = KotlinCompilerSettings.getInstance(project).getSettings();
KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2jsArguments, compilerSettings, messageCollector, environment,
outputItemsCollector, srcFiles, libraryFiles, outFile);
TranslatingCompilerUtils.reportOutputs(sink, environment.getOutput(), outputItemsCollector);
}
@Nullable
private static Module getModule(@NotNull CompileContext context, @NotNull Chunk<Module> moduleChunk) {
if (moduleChunk.getNodes().size() != 1) {
context.addMessage(CompilerMessageCategory.ERROR, "K2JSCompiler does not support multiple modules.", null, -1, -1);
return null;
}
return moduleChunk.getNodes().iterator().next();
}
// 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) {
for (OrderEntry entry : ModuleRootManager.getInstance(dependentModule).getOrderEntries()) {
if (entry instanceof ModuleOrderEntry) {
ModuleOrderEntry moduleEntry = (ModuleOrderEntry) entry;
if (!moduleEntry.getScope().isForProductionCompile()) {
continue;
}
Module module = moduleEntry.getModule();
if (module == null) {
continue;
}
if (modules.add(module) && moduleEntry.isExported()) {
collectModuleDependencies(module, modules);
}
}
}
}
private static VirtualFile[] getSourceFiles(@NotNull Module module) {
return CompilerManager.getInstance(module.getProject()).createModuleCompileScope(module, false)
.getFiles(JetFileType.INSTANCE, true);
}
private static List<String> getLibraryFiles(@NotNull Module module) {
List<String> result = new ArrayList<String>();
List<String> libLocationAndTarget = ProjectStructureUtil.getLibLocationForProject(module);
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());
}
}
}
for (String file : libLocationAndTarget) {
result.add(file);
}
return result;
}
@NotNull
@Override
public String getDescription() {
return "Kotlin to JavaScript compiler";
}
@Override
public boolean validateConfiguration(CompileScope scope) {
return true;
}
}
@@ -1,248 +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.plugin.compiler;
import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.AnnotationOrderRootType;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Chunk;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.jet.cli.common.arguments.K2JVMCompilerArguments;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.compiler.CompilerSettings;
import org.jetbrains.jet.compiler.runner.*;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder;
import org.jetbrains.jet.plugin.compiler.configuration.KotlinCommonCompilerArgumentsHolder;
import org.jetbrains.jet.plugin.compiler.configuration.KotlinCompilerSettings;
import org.jetbrains.jet.plugin.project.ProjectStructureUtil;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class K2JvmTranslatingCompiler implements TranslatingCompiler {
@Override
public boolean isCompilableFile(VirtualFile virtualFile, CompileContext compileContext) {
if (!(virtualFile.getFileType() instanceof JetFileType)) {
return false;
}
Module module = compileContext.getModuleByFile(virtualFile);
if (module != null && ProjectStructureUtil.isJsKotlinModule(module)) {
return false;
}
return true;
}
@NotNull
@Override
public String getDescription() {
return "Jet Language Compiler";
}
@Override
public boolean validateConfiguration(CompileScope compileScope) {
return true;
}
@Override
public void compile(
CompileContext compileContext,
Chunk<Module> moduleChunk,
VirtualFile[] virtualFiles,
OutputSink outputSink) {
if (virtualFiles.length == 0) return;
List<VirtualFile> productionFiles = new ArrayList<VirtualFile>();
List<VirtualFile> testFiles = new ArrayList<VirtualFile>();
for (VirtualFile file : virtualFiles) {
boolean inTests = ((CompileContextEx)compileContext).isInTestSourceContent(file);
if (inTests) {
testFiles.add(file);
}
else {
productionFiles.add(file);
}
}
Module module = compileContext.getModuleByFile(virtualFiles[0]);
doCompile(compileContext, moduleChunk, productionFiles, module, outputSink, false);
doCompile(compileContext, moduleChunk, testFiles, module, outputSink, true);
}
private static void doCompile(
final CompileContext compileContext,
Chunk<Module> moduleChunk,
List<VirtualFile> files,
Module module,
OutputSink outputSink,
boolean tests
) {
if (files.isEmpty()) return;
MessageCollector messageCollector = new MessageCollectorAdapter(compileContext);
CompilerEnvironment environment = TranslatingCompilerUtils.getEnvironmentFor(compileContext, module, tests);
if (!environment.success()) {
environment.reportErrorsTo(messageCollector);
return;
}
File outputDir = environment.getOutput();
File scriptFile = tryToWriteScriptFile(compileContext, moduleChunk, files, module, tests,
compileContext.getModuleOutputDirectory(module),
outputDir);
if (scriptFile == null) return;
OutputItemsCollectorImpl collector = new OutputItemsCollectorImpl() {
@Override
public void add(Collection<File> sourceFiles, File outputFile) {
super.add(sourceFiles, outputFile);
compileContext.getProgressIndicator().setText("Emitting: " + outputFile);
}
};
runCompiler(module.getProject(), messageCollector, environment, scriptFile, collector);
TranslatingCompilerUtils.reportOutputs(outputSink, outputDir, collector);
}
private static void runCompiler(
Project project,
MessageCollector messageCollector,
CompilerEnvironment environment,
File scriptFile,
OutputItemsCollector outputItemsCollector
) {
CommonCompilerArguments commonArguments = KotlinCommonCompilerArgumentsHolder.getInstance(project).getSettings();
K2JVMCompilerArguments k2jvmArguments = Kotlin2JvmCompilerArgumentsHolder.getInstance(project).getSettings();
CompilerSettings compilerSettings = KotlinCompilerSettings.getInstance(project).getSettings();
KotlinCompilerRunner.runK2JvmCompiler(commonArguments, k2jvmArguments, compilerSettings,
messageCollector, environment, scriptFile, outputItemsCollector);
}
public static File tryToWriteScriptFile(
CompileContext compileContext,
Chunk<Module> moduleChunk,
List<VirtualFile> files,
Module module,
boolean tests, VirtualFile mainOutput, File outputDir
) {
List<File> sourceFiles = ContainerUtil.newArrayList(ioFiles(files));
ModuleChunk chunk = new ModuleChunk((CompileContextEx)compileContext, moduleChunk, Collections.<Module, List<VirtualFile>>emptyMap());
String moduleName = moduleChunk.getNodes().iterator().next().getName();
File outputDirectoryForTests = ioFile(compileContext.getModuleOutputDirectoryForTests(module));
File moduleOutputDirectory = ioFile(compileContext.getModuleOutputDirectory(module));
// Filter the output we are writing to
Set<File> outputDirectoriesToFilter = ContainerUtil.newHashSet(outputDirectoryForTests);
if (!tests) {
outputDirectoriesToFilter.add(moduleOutputDirectory);
}
CharSequence script = KotlinModuleScriptBuilderFactory.INSTANCE.create(null).addModule(
moduleName,
moduleOutputDirectory.getAbsolutePath(),
getDependencyProvider(chunk, tests, mainOutput),
sourceFiles,
tests,
outputDirectoriesToFilter
).asText();
File scriptFile = new File(outputDir, "script.ktm");
try {
FileUtil.writeToFile(scriptFile, script.toString());
}
catch (IOException e) {
compileContext.addMessage(CompilerMessageCategory.ERROR, "[Internal Error] Cannot write script to " + scriptFile.getAbsolutePath(), "", -1, -1);
return null;
}
return scriptFile;
}
private static KotlinModuleDescriptionBuilder.DependencyProvider getDependencyProvider(
final ModuleChunk chunk,
final boolean tests,
final VirtualFile mainOutputPath
) {
return new KotlinModuleDescriptionBuilder.DependencyProvider() {
@Override
public void processClassPath(@NotNull KotlinModuleDescriptionBuilder.DependencyProcessor processor) {
// TODO: have a bootclasspath in script API
processor.processClassPathSection("Boot classpath", ioFiles(chunk.getCompilationBootClasspathFiles()));
processor.processClassPathSection("Compilation classpath", ioFiles(chunk.getCompilationClasspathFiles()));
// This is for java files in same roots
processor.processClassPathSection("Java classpath (for Java sources)", ioFiles(Arrays.asList(chunk.getSourceRoots())));
if (tests && mainOutputPath != null) {
processor.processClassPathSection("Main output", Arrays.asList(ioFile(mainOutputPath)));
}
processor.processAnnotationRoots(getAnnotationRootPaths(chunk));
}
};
}
private static List<File> getAnnotationRootPaths(ModuleChunk chunk) {
List<File> annotationPaths = ContainerUtil.newArrayList();
for (Module module : chunk.getModules()) {
for (VirtualFile file : OrderEnumerator.orderEntries(module).roots(AnnotationOrderRootType.getInstance()).getRoots()) {
annotationPaths.add(ioFile(file));
}
}
return annotationPaths;
}
private static Collection<File> ioFiles(Collection<VirtualFile> files) {
return ContainerUtil.map(files, new Function<VirtualFile, File>() {
@Override
public File fun(VirtualFile file) {
return ioFile(file);
}
});
}
private static File ioFile(VirtualFile file) {
return new File(path(file));
}
private static String path(VirtualFile root) {
String path = root.getPath();
if (path.endsWith("!/")) {
return path.substring(0, path.length() - 2);
}
return path;
}
}
@@ -1,71 +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.plugin.compiler;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.compiler.runner.CompilerRunnerConstants;
import static com.intellij.openapi.compiler.CompilerMessageCategory.*;
class MessageCollectorAdapter implements MessageCollector {
private final CompileContext compileContext;
public MessageCollectorAdapter(CompileContext compileContext) {
this.compileContext = compileContext;
}
@Override
public void report(
@NotNull CompilerMessageSeverity severity,
@NotNull String message,
@NotNull CompilerMessageLocation location
) {
CompilerMessageCategory category = category(severity);
String prefix = "";
if (severity == CompilerMessageSeverity.EXCEPTION) {
prefix = CompilerRunnerConstants.INTERNAL_ERROR_PREFIX;
}
compileContext.addMessage(category, prefix + message, "file://" + location.getPath(), location.getLine(), location.getColumn());
if (severity == CompilerMessageSeverity.LOGGING) {
compileContext.getProgressIndicator().setText(message);
}
}
private static CompilerMessageCategory category(CompilerMessageSeverity severity) {
switch (severity) {
case INFO:
return INFORMATION;
case ERROR:
return ERROR;
case WARNING:
return WARNING;
case EXCEPTION:
return ERROR;
case LOGGING:
case OUTPUT:
return STATISTICS;
}
throw new IllegalArgumentException("Unknown severity: " + severity);
}
}
@@ -1,78 +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.plugin.compiler;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.compiler.impl.javaCompiler.OutputItemImpl;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.compiler.runner.CompilerEnvironment;
import org.jetbrains.jet.compiler.runner.OutputItemsCollectorImpl;
import org.jetbrains.jet.compiler.runner.SimpleOutputItem;
import org.jetbrains.jet.utils.KotlinPaths;
import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
import java.util.List;
import java.util.Set;
public final class TranslatingCompilerUtils {
private TranslatingCompilerUtils() {
}
@NotNull
public static CompilerEnvironment getEnvironmentFor(@NotNull CompileContext compileContext, @NotNull Module module, boolean tests) {
VirtualFile mainOutput = compileContext.getModuleOutputDirectory(module);
VirtualFile outputDirectoryForTests = compileContext.getModuleOutputDirectoryForTests(module);
File outputDir = tests ? toNullableIoFile(outputDirectoryForTests) : toNullableIoFile(mainOutput);
KotlinPaths kotlinPaths = PathUtil.getKotlinPathsForIdeaPlugin();
return CompilerEnvironment.getEnvironmentFor(kotlinPaths, outputDir, null);
}
@Nullable
public static File toNullableIoFile(@Nullable VirtualFile file) {
if (file == null) return null;
return new File(file.getPath());
}
public static void reportOutputs(
TranslatingCompiler.OutputSink outputSink,
File outputDir,
OutputItemsCollectorImpl outputItemsCollector
) {
Set<VirtualFile> sources = Sets.newHashSet();
List<TranslatingCompiler.OutputItem> outputs = Lists.newArrayList();
for (SimpleOutputItem output : outputItemsCollector.getOutputs()) {
LocalFileSystem.getInstance().refreshAndFindFileByIoFile(output.getOutputFile());
for (File sourceFile : output.getSourceFiles()) {
VirtualFile virtualFileForSourceFile = LocalFileSystem.getInstance().findFileByIoFile(sourceFile);
sources.add(virtualFileForSourceFile);
outputs.add(new OutputItemImpl(output.getOutputFile().getPath(), virtualFileForSourceFile));
}
}
outputSink.add(outputDir.getPath(), outputs, sources.toArray(VirtualFile.EMPTY_ARRAY));
}
}
@@ -1,107 +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.plugin.compilerMessages;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestCase;
import kotlin.Function1;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public abstract class IDECompilerMessagingTest extends PlatformTestCase {
protected void performTest(@NotNull Function1<MessageChecker, Void> whatToExpect,
@NotNull TranslatingCompiler compiler, @NotNull String testDataPath) {
String pathToTestDir = testDataPath + "/" + getTestName(true);
VirtualFile testDir = getFile(testDataPath, "");
VirtualFile sampleFile = getFile(testDataPath, "/src/test.kt");
VirtualFile outDirectory = getOutDirectory(pathToTestDir, testDir);
VirtualFile root = getFile(testDataPath, "/src");
MockCompileContext mockCompileContext = new MockCompileContext(myModule, outDirectory, root);
MockModuleChunk mockModuleChunk = new MockModuleChunk(myModule);
setSourceEntryForModule(root);
assert sampleFile != null;
compile(compiler, sampleFile, mockCompileContext, mockModuleChunk);
checkMessages(whatToExpect, mockCompileContext);
}
protected VirtualFile getFile(@NotNull String testDataPath, @NotNull String relativePath) {
String pathToFile = testDataPath + "/" + getTestName(true) + relativePath;
VirtualFile file = LocalFileSystem.getInstance().findFileByPath(pathToFile);
Assert.assertNotNull("Can't find path " + pathToFile, file);
return file;
}
private void checkMessages(@NotNull Function1<MessageChecker, Void> whatToExpect, @NotNull MockCompileContext mockCompileContext) {
MessageChecker checker = new MessageChecker(mockCompileContext);
checkHeader(checker);
whatToExpect.invoke(checker);
checker.finish();
}
private static void compile(@NotNull TranslatingCompiler compiler,
@NotNull VirtualFile sampleFile,
@NotNull MockCompileContext mockCompileContext,
@NotNull MockModuleChunk mockModuleChunk) {
compiler.compile(mockCompileContext, mockModuleChunk, new VirtualFile[] {sampleFile}, new MockOutputSink());
}
private void setSourceEntryForModule(final VirtualFile root) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ModifiableRootModel model = ModuleRootManager.getInstance(myModule).getModifiableModel();
ContentEntry entry = model.addContentEntry(root);
entry.addSourceFolder(root, false);
model.commit();
}
});
}
protected abstract void checkHeader(@NotNull MessageChecker checker);
@NotNull
private VirtualFile getOutDirectory(@NotNull String pathToTestDir, @NotNull VirtualFile testDir) {
VirtualFile outDirectory = LocalFileSystem.getInstance().findFileByPath(pathToTestDir + "/out");
if (outDirectory == null) {
try {
outDirectory = LocalFileSystem.getInstance().createChildDirectory(this, testDir, "out");
}
catch (IOException e) {
fail();
}
}
return outDirectory;
}
protected <T extends TranslatingCompiler> T getCompiler(Class<T> aClass) {
T[] compilers = CompilerManager.getInstance(getProject()).getCompilers(aClass);
assert compilers.length == 1;
return compilers[0];
}
}
@@ -1,89 +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.plugin.compilerMessages;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import org.jetbrains.jet.plugin.compiler.K2JvmTranslatingCompiler;
import static org.jetbrains.jet.plugin.compilerMessages.Message.error;
import static org.jetbrains.jet.plugin.compilerMessages.Message.warning;
public final class JetCompilerMessagingTest extends IDECompilerMessagingTest {
private static final String TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/compilerMessages/k2jvm";
public void testHelloWorld() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
//nothing apart from header
return null;
}
});
}
public void testSimpleWarning() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
checker.expect(warning().text("Unnecessary non-null assertion (!!) on a non-null receiver of type kotlin.String")
.at("test.kt", 4, 4));
return null;
}
});
}
public void testSimpleError() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
checker.expect(
error().text("A 'return' expression required in a function with a block body ('{...}')").at("test.kt", 5, 1));
return null;
}
});
}
public void testVisibilityError() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
checker
.expect(error().text("'f' hides member of supertype 'TestTrait' and needs 'override' modifier").at("test.kt", 6, 5))
.expect(error().text("Cannot weaken access privilege 'public' for 'f' in 'TestTrait'").at("test.kt", 6, 9))
;
return null;
}
});
}
private void doTest(@NotNull Function1<MessageChecker, Void> whatToExpect) {
performTest(whatToExpect, getCompiler(K2JvmTranslatingCompiler.class), TEST_DATA_PATH);
}
@Override
protected void checkHeader(@NotNull MessageChecker checker) {
checker.expect(Message.info().textStartsWith("Using kotlinHome="));
checker.expect(Message.info().textStartsWith("Invoking compiler"));
checker.expect(Message.info().textStartsWith("Kotlin Compiler version"));
checker.expect(Message.stats().textStartsWith("Using Kotlin home directory"));
checker.expect(Message.stats().text("Configuring the compilation environment"));
}
}
@@ -1,108 +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.plugin.compilerMessages;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.util.PathUtil;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import org.jetbrains.jet.plugin.compiler.K2JsTranslatingCompiler;
import org.jetbrains.jet.testing.ConfigLibraryUtil;
import java.io.File;
import static org.jetbrains.jet.plugin.compilerMessages.Message.*;
public final class K2JSCompilerMessagingTest extends IDECompilerMessagingTest {
private static final String TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/compilerMessages/k2js";
public void testHelloWorld() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
//nothing apart from header
return null;
}
});
}
public void testSimpleWarning() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
checker.expect(warning().text("Condition 't != null' is always 'true'")
.at("test.kt", 3, 7));
return null;
}
});
}
public void testSimpleError() {
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
checker.expect(
error().text("A 'return' expression required in a function with a block body ('{...}')").at("test.kt", 5, 1));
return null;
}
});
}
public void testLib() {
NewLibraryEditor editor = new NewLibraryEditor(null, null);
editor.setName("testLib");
String path = PathUtil.getLocalPath(getFile(TEST_DATA_PATH, "/src/lib.zip"));
assert path != null : "Can't get local path";
String libUrl = VfsUtil.getUrlForLibraryRoot(new File(path));
editor.addRoot(libUrl, OrderRootType.CLASSES);
editor.addRoot(libUrl, OrderRootType.SOURCES);
try {
ConfigLibraryUtil.addLibrary(editor, myModule);
doTest(new Function1<MessageChecker, Void>() {
@Override
public Void invoke(MessageChecker checker) {
//nothing apart from header
return null;
}
});
}
finally {
ConfigLibraryUtil.removeLibrary(myModule, "testLib");
}
}
private void doTest(@NotNull Function1<MessageChecker, Void> whatToExpect) {
performTest(whatToExpect, getCompiler(K2JsTranslatingCompiler.class), TEST_DATA_PATH);
}
@Override
protected void checkHeader(@NotNull MessageChecker checker) {
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"));
}
}
@@ -1,120 +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.plugin.compilerMessages;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@SuppressWarnings("ConstantConditions")
public final class Message {
@NotNull
public static Message warning() {
return new Message(CompilerMessageCategory.WARNING);
}
@NotNull
public static Message error() {
return new Message(CompilerMessageCategory.ERROR);
}
@NotNull
public static Message info() {
return new Message(CompilerMessageCategory.INFORMATION);
}
@NotNull
public static Message stats() {
return new Message(CompilerMessageCategory.STATISTICS);
}
@NotNull
public CompilerMessageCategory category;
@Nullable
public String url = null;
@Nullable
public String message = null;
@Nullable
public String textStartsWith = null;
@Nullable
private String textMatchesRegexp = null;
public int column = -1;
public int line = -1;
public Message(CompilerMessageCategory category) {
this.category = category;
}
public Message(CompilerMessageCategory category, String message, String url, int num, int num1) {
this(category);
text(message).at(url, num, num1);
}
public Message at(String url, int line, int column) {
this.url = url;
this.line = line;
this.column = column;
return this;
}
public Message text(String message) {
this.message = message;
return this;
}
public Message textStartsWith(String message) {
this.textStartsWith = message;
return this;
}
public Message textMatchesRegexp(String regexp) {
this.textMatchesRegexp = regexp;
return this;
}
public void check(@NotNull Message other) {
checkMessages(other);
Assert.assertEquals("Error category for message " + this, this.category, other.category);
Assert.assertEquals("Invalid position (different line) for message:\n" + this + "\n", this.line, other.line);
Assert.assertEquals("Invalid position (different column) for message:\n" + this + "\n", this.column, other.column);
if (this.url != null) {
Assert.assertTrue(other.url.endsWith(this.url));
}
}
private void checkMessages(Message other) {
if (textStartsWith != null) {
Assert.assertTrue("Message should start with:\n" + textStartsWith + "\nBut it is:\n" + other.message,
other.message.startsWith(textStartsWith));
return;
}
if (textMatchesRegexp != null) {
Assert.assertTrue("Message should match regexp:\n" + textMatchesRegexp + "\nBut it is:\n" + other.message,
other.message.matches(textMatchesRegexp));
return;
}
Assert.assertEquals(this.message, other.message);
}
@Override
public String toString() {
return category + ": " + message + " at " + line + ":" + column + " in " + url;
}
}
@@ -1,55 +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.plugin.compilerMessages;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public final class MessageChecker {
private final Iterator<Message> iterator;
public MessageChecker(@NotNull MockCompileContext context) {
this.iterator = context.getReceivedMessages().iterator();
}
@NotNull
public MessageChecker expect(@NotNull Message message) {
assertTrue("Expected message not present:\n" + message, iterator.hasNext());
message.check(iterator.next());
return this;
}
public void finish() {
if (iterator.hasNext()) {
StringBuilder builder = messagesToString(iterator);
fail("More messages than expected:\n" + builder.toString());
}
}
private StringBuilder messagesToString(Iterator<Message> iterator) {
StringBuilder builder = new StringBuilder();
while (iterator.hasNext()) {
builder.append(iterator.next()).append("\n\n");
}
return builder;
}
}
@@ -1,238 +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.plugin.compilerMessages;
import com.google.common.collect.Lists;
import com.intellij.compiler.make.DependencyCache;
import com.intellij.mock.MockProgressIndicator;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.Compiler;
import com.intellij.openapi.compiler.CompilerMessage;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class MockCompileContext implements CompileContextEx {
@NotNull
private final List<Message> receivedMessages = Lists.newArrayList();
@NotNull
private final Module module;
@NotNull
private final VirtualFile outputDirectory;
@NotNull
private final VirtualFile sourceRoot;
public MockCompileContext(@NotNull Module module, @NotNull VirtualFile outputDir, @NotNull VirtualFile root) {
this.module = module;
this.outputDirectory = outputDir;
this.sourceRoot = root;
}
@NotNull
public List<Message> getReceivedMessages() {
return receivedMessages;
}
@Override
public DependencyCache getDependencyCache() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getDependencyCache");
}
@Override
public VirtualFile getSourceFileByOutputFile(VirtualFile outputFile) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getSourceFileByOutputFile");
}
@Override
public void addMessage(CompilerMessage message) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#addMessage");
}
@NotNull
@Override
public Set<VirtualFile> getTestOutputDirectories() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getTestOutputDirectories");
}
@Override
public boolean isInTestSourceContent(@NotNull VirtualFile fileOrDir) {
return false;
}
@Override
public boolean isInSourceContent(@NotNull VirtualFile fileOrDir) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#isInSourceContent");
}
@Override
public void addScope(CompileScope additionalScope) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#addScope");
}
@Override
public long getStartCompilationStamp() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getStartCompilationStamp");
}
@Override
public void recalculateOutputDirs() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#recalculateOutputDirs");
}
@Override
public void markGenerated(Collection<VirtualFile> files) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#markGenerated");
}
@Override
public boolean isGenerated(VirtualFile file) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#isGenerated");
}
@Override
public void assignModule(@NotNull VirtualFile root,
@NotNull Module module,
boolean isTestSource,
@Nullable Compiler compiler) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#assignModule");
}
@Override
public void addMessage(CompilerMessageCategory category, String message, @Nullable String url, int lineNum, int columnNum) {
receivedMessages.add(new Message(category, message, url, lineNum, columnNum));
}
@Override
public void addMessage(CompilerMessageCategory category,
String message,
@Nullable String url,
int lineNum,
int columnNum,
Navigatable navigatable) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#addMessage");
}
@Override
public CompilerMessage[] getMessages(CompilerMessageCategory category) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getMessages");
}
@Override
public int getMessageCount(CompilerMessageCategory category) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getMessageCount");
}
@NotNull
@Override
public ProgressIndicator getProgressIndicator() {
return new MockProgressIndicator();
}
@Override
public CompileScope getCompileScope() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getCompileScope");
}
@Override
public CompileScope getProjectCompileScope() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getProjectCompileScope");
}
@Override
public void requestRebuildNextTime(String message) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#requestRebuildNextTime");
}
@Override
public boolean isRebuildRequested() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext.isRebuildRequested");
}
@Nullable
@Override
public String getRebuildReason() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext.getRebuildReason");
}
@Override
public Module getModuleByFile(VirtualFile file) {
return module;
}
@Override
public VirtualFile[] getSourceRoots(Module module) {
return new VirtualFile[] {sourceRoot};
}
@Override
public VirtualFile[] getAllOutputDirectories() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getAllOutputDirectories");
}
@Override
public VirtualFile getModuleOutputDirectory(Module module) {
return outputDirectory;
}
@Override
public VirtualFile getModuleOutputDirectoryForTests(Module module) {
return outputDirectory;
}
@Override
public boolean isMake() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#isMake");
}
@Override
public boolean isRebuild() {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#isRebuild");
}
@Override
public Project getProject() {
return module.getProject();
}
@Override
public boolean isAnnotationProcessorsEnabled() {
throw new UnsupportedOperationException(
"org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#isAnnotationProcessorsEnabled");
}
@Override
public <T> T getUserData(@NotNull Key<T> key) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#getUserData");
}
@Override
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
throw new UnsupportedOperationException("org.jetbrains.jet.plugin.compilerMessages.MockCompileContext#putUserData");
}
}
@@ -1,26 +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.plugin.compilerMessages;
import com.intellij.openapi.module.Module;
import com.intellij.util.Chunk;
public class MockModuleChunk extends Chunk<Module> {
public MockModuleChunk(Module module) {
super(module);
}
}
@@ -1,29 +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.plugin.compilerMessages;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.vfs.VirtualFile;
import java.util.Collection;
public class MockOutputSink implements TranslatingCompiler.OutputSink {
@Override
public void add(String outputRoot, Collection<TranslatingCompiler.OutputItem> items, VirtualFile[] filesToRecompile) {
// do nothing
}
}