package org.mule.devkit.idea.compiler; import com.intellij.compiler.impl.CompilerUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.CompilerMessageCategory; import com.intellij.openapi.compiler.SourceGeneratingCompiler; import com.intellij.openapi.compiler.ValidityState; import com.intellij.openapi.compiler.ex.CompileContextEx; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.DataInput; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MuleAptCompiler implements SourceGeneratingCompiler { private static final GenerationItem[] EMPTY_GENERATION_ITEM_ARRAY = {}; private static final Pattern ourMessagePattern = Pattern.compile("(.+):(\\d+):.+"); public VirtualFile getPresentableFile(CompileContext compileContext, Module module, VirtualFile virtualFile, VirtualFile virtualFile1) { return null; } public GenerationItem[] getGenerationItems(CompileContext compileContext) { return ApplicationManager.getApplication().runReadAction(new MuleAptPrepareAction(compileContext)); } private static void addMessages(final CompileContext context, final Map<CompilerMessageCategory, List<String>> messages) { addMessages(context, messages, null); } @NotNull private static String getPresentableFile(@NotNull String url, @Nullable Map<VirtualFile, VirtualFile> presentableFilesMap) { final VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); if (file == null) { return url; } if (presentableFilesMap == null) { return url; } for (Map.Entry<VirtualFile, VirtualFile> entry : presentableFilesMap.entrySet()) { if (file == entry.getValue()) { return entry.getKey().getUrl(); } } return url; } private static void addMessages(final CompileContext context, final Map<CompilerMessageCategory, List<String>> messages, @Nullable final Map<VirtualFile, VirtualFile> presentableFilesMap) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { if (context.getProject().isDisposed()) { return; } for (CompilerMessageCategory category : messages.keySet()) { List<String> messageList = messages.get(category); for (String message : messageList) { String url = null; int line = -1; Matcher matcher = ourMessagePattern.matcher(message); if (matcher.matches()) { String fileName = matcher.group(1); if (new File(fileName).exists()) { url = getPresentableFile("file://" + fileName, presentableFilesMap); line = Integer.parseInt(matcher.group(2)); } } context.addMessage(category, message, url, line, -1); } } } }); } private static GenerationItem[] doGenerate(final CompileContext context, GenerationItem[] items) { List<GenerationItem> results = new ArrayList<GenerationItem>(items.length); for (GenerationItem item : items) { if (item instanceof MuleAptGenerationItem) { final MuleAptGenerationItem aptItem = (MuleAptGenerationItem) item; if (!isModuleAffected(context, aptItem.getModule())) { continue; } try { Map<CompilerMessageCategory, List<String>> messages = MuleApt.compile(aptItem); addMessages(context, messages); if (messages.get(CompilerMessageCategory.ERROR).isEmpty()) { results.add(aptItem); } } catch (final IOException e) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { if (context.getProject().isDisposed()) { return; } context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1); } }); } } } return results.toArray(new GenerationItem[results.size()]); } public static boolean isModuleAffected(CompileContext context, Module module) { return ArrayUtil.find(context.getCompileScope().getAffectedModules(), module) >= 0; } public GenerationItem[] generate(final CompileContext compileContext, final GenerationItem[] items, VirtualFile virtualFile) { if (items != null && items.length > 0) { compileContext.getProgressIndicator().setText("Generating Mule Code"); Computable<GenerationItem[]> computation = new Computable<GenerationItem[]>() { public GenerationItem[] compute() { if (compileContext.getProject().isDisposed()) { return EMPTY_GENERATION_ITEM_ARRAY; } return doGenerate(compileContext, items); } }; GenerationItem[] generationItems = computation.compute(); List<VirtualFile> generatedVFiles = new ArrayList<VirtualFile>(); for (GenerationItem aptGenerationItem : generationItems) { List<File> files = new ArrayList<File>(); CompilerUtil.collectFiles(files, new File(aptGenerationItem.getModule().getModuleFile().getParent().getPath() + "/target/generated-sources"), new FileFilter() { public boolean accept(File file) { return true; } }); CompilerUtil.refreshIOFiles(files); for (File file : files) { VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(file); generatedVFiles.add(generatedVFile); } } if (compileContext instanceof CompileContextEx) { ((CompileContextEx) compileContext).markGenerated(generatedVFiles); } return generationItems; } return EMPTY_GENERATION_ITEM_ARRAY; } @NotNull public String getDescription() { return "Mule DevKit Code Generator"; } public boolean validateConfiguration(CompileScope compileScope) { return true; } public ValidityState createValidityState(DataInput dataInput) throws IOException { return null; //To change body of implemented methods use File | Settings | File Templates. } }