/* * Copyright 2013 original Randori IntelliJ Plugin authors. * * 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 randori.plugin.compiler; import com.intellij.compiler.impl.CompilerUtil; import com.intellij.lang.javascript.ActionScriptFileType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.Result; import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.compiler.TranslatingCompiler; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Chunk; import com.intellij.util.ThrowableRunnable; import org.jetbrains.annotations.NotNull; import randori.plugin.components.RandoriProjectComponent; import randori.plugin.configuration.RandoriCompilerModel; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * IDEA Compiler class for calling the internal compiler API. * * @author Frédéric THOMAS */ class RandoriCompiler implements TranslatingCompiler { private static final Logger LOG = Logger.getInstance("#randori.compiler.RandoriCompiler"); private final Project project; private final RandoriProjectComponent projectComponent; private int sessionId; private RandoriCompilerSession compilerSession; public RandoriCompiler(Project project) { this.project = project; projectComponent = project.getComponent(RandoriProjectComponent.class); } @Override public boolean isCompilableFile(VirtualFile file, CompileContext context) { return FileUtilRt.extensionEquals(file.getPath(), ActionScriptFileType.INSTANCE.getDefaultExtension()); } @Override public void compile(CompileContext context, Chunk<Module> moduleChunk, VirtualFile[] files, OutputSink sink) { context.getProgressIndicator().checkCanceled(); int moduleCount = moduleChunk.getNodes().size(); for (Module module : moduleChunk.getNodes()) { final boolean isLastModule = --moduleCount == 0; List<VirtualFile> modifiedFiles = project.getComponent(RandoriProjectComponent.class).getModifiedFiles(); boolean doClean = true; boolean success; if (context.hashCode() != sessionId) { sessionId = context.hashCode(); compilerSession = new RandoriCompilerSession(project); } else doClean = false; if (context.isMake() && modifiedFiles.size() > 0) { LOG.info("Starting Randori compiler... Make " + module.getName()); context.getProgressIndicator().setText("Starting Randori compiler... Make " + module.getName()); success = compilerSession.make(module); } else if (context.isRebuild()) { if (doClean) clearAffectedOutputPathsIfPossible(context, moduleChunk.getNodes().iterator()); LOG.info("Starting Randori compiler... Rebuild " + module.getName()); context.getProgressIndicator().setText("Starting Randori compiler... Rebuild " + module.getName()); success = compilerSession.build(module); } else return; if (success) { if (isLastModule && modifiedFiles.size() > 0) modifiedFiles.removeAll(modifiedFiles); } else { context.getProgressIndicator().cancel(); } // If compilation failed or it is the last module, Show the problem window if (!success || isLastModule) ApplicationManager.getApplication().invokeLater( new RandoriCompilerSession.ProblemBuildRunnable(project, RandoriCompilerSession .getLastCompiler(), true)); } } @NotNull @Override public String getDescription() { return "Randori Compiler"; } @Override public boolean validateConfiguration(CompileScope scope) { return projectComponent.validateConfiguration(scope); } private void clearAffectedOutputPathsIfPossible(final CompileContext context, final Iterator<Module> moduleIterator) { final List<File> outPutDirs = new ReadAction<List<File>>() { protected void run(final Result<List<File>> result) { final List<File> dirs = new ArrayList<File>(); final RandoriCompilerModel projectModel = RandoriCompilerModel.getInstance(project).getState(); final VirtualFile baseDir = project.getBaseDir(); assert projectModel != null; baseDir.findFileByRelativePath(projectModel.getBasePath()); File generatedDir = new File(FileUtil.toSystemDependentName(baseDir.getPath() + File.separator + projectModel.getBasePath())); dirs.add(generatedDir); while (moduleIterator.hasNext()) { VirtualFile outPutDir = context.getModuleOutputDirectory(moduleIterator.next()); if (outPutDir != null) { dirs.add(new File(outPutDir.getCanonicalPath())); } } result.setResult(dirs); } }.execute().getResultObject(); if (outPutDirs.size() > 0) { CompilerUtil.runInContext(context, CompilerBundle.message("progress.clearing.output"), new ThrowableRunnable<RuntimeException>() { public void run() { CompilerUtil.clearOutputDirectories(outPutDirs); } }); } } }