mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
annotation processors:
1. invoke per-module 2. reworked handling of output paths for generated sources (UI coming soon)
This commit is contained in:
@@ -80,6 +80,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
private boolean myEnableAnnotationProcessors = false;
|
||||
private final Map<String, String> myProcessorsMap = new HashMap<String, String>(); // map: AnnotationProcessorName -> options
|
||||
private boolean myObtainProcessorsFromClasspath = true;
|
||||
private boolean myStoreGenerateSourcesUnderModuleContent = false;
|
||||
private String myGeneratedDirName = "generated";
|
||||
private String myProcessorPath = "";
|
||||
private final Set<Module> myExcludedModules = new HashSet<Module>();
|
||||
private final Set<String> myExcludedModuleNames = new HashSet<String>();
|
||||
@@ -310,6 +312,24 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
myObtainProcessorsFromClasspath = obtainProcessorsFromClasspath;
|
||||
}
|
||||
|
||||
public boolean isStoreGenerateSourcesUnderModuleContent(Module module) {
|
||||
// todo: make this per-module setting
|
||||
return myStoreGenerateSourcesUnderModuleContent;
|
||||
}
|
||||
|
||||
public void setStoreGenerateSourcesUnderModuleContent(boolean storeGenerateSourcesUnderModuleContent) {
|
||||
myStoreGenerateSourcesUnderModuleContent = storeGenerateSourcesUnderModuleContent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getGeneratedDirName() {
|
||||
return myGeneratedDirName;
|
||||
}
|
||||
|
||||
public void setGeneratedDirName(String generatedDirName) {
|
||||
myGeneratedDirName = generatedDirName;
|
||||
}
|
||||
|
||||
public String getProcessorPath() {
|
||||
return myProcessorPath;
|
||||
}
|
||||
@@ -522,6 +542,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
if (annotationProcessingSettings != null) {
|
||||
myEnableAnnotationProcessors = Boolean.valueOf(annotationProcessingSettings.getAttributeValue("enabled", "false"));
|
||||
myObtainProcessorsFromClasspath = Boolean.valueOf(annotationProcessingSettings.getAttributeValue("useClasspath", "true"));
|
||||
myStoreGenerateSourcesUnderModuleContent = Boolean.valueOf(annotationProcessingSettings.getAttributeValue("storeGeneratedUnderContent", "false"));
|
||||
myGeneratedDirName = annotationProcessingSettings.getAttributeValue("generatedDirName", "generated");
|
||||
|
||||
final StringBuilder pathBuilder = new StringBuilder();
|
||||
for (Element pathElement : ((Collection<Element>)annotationProcessingSettings.getChildren("processorPath"))) {
|
||||
@@ -596,6 +618,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
parentNode.addContent(annotationProcessingSettings);
|
||||
annotationProcessingSettings.setAttribute("enabled", String.valueOf(myEnableAnnotationProcessors));
|
||||
annotationProcessingSettings.setAttribute("useClasspath", String.valueOf(myObtainProcessorsFromClasspath));
|
||||
annotationProcessingSettings.setAttribute("storeGeneratedUnderContent", String.valueOf(myStoreGenerateSourcesUnderModuleContent));
|
||||
annotationProcessingSettings.setAttribute("generatedDirName", myGeneratedDirName);
|
||||
if (myProcessorPath.length() > 0) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(myProcessorPath, File.pathSeparator, false);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
|
||||
@@ -64,8 +64,8 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
myEventPublisher = messageBus.syncPublisher(CompilerTopics.COMPILATION_STATUS);
|
||||
|
||||
// predefined compilers
|
||||
addTranslatingCompiler(new JavaCompiler(myProject), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
|
||||
addCompiler(new AnnotationProcessingCompiler(project));
|
||||
addTranslatingCompiler(new AnnotationProcessingCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA, StdFileTypes.CLASS)));
|
||||
addTranslatingCompiler(new JavaCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
|
||||
addCompiler(new ResourceCompiler(project, compilerConfiguration));
|
||||
addCompiler(new RmicCompiler());
|
||||
addCompiler(new IncrementalArtifactsCompiler());
|
||||
|
||||
@@ -51,6 +51,7 @@ import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
@@ -138,6 +139,13 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final Module module = getModuleByFile(file);
|
||||
if (module != null) {
|
||||
final String procGenRoot = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (VfsUtil.isAncestor(new File(procGenRoot), new File(file.getPath()), true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +53,7 @@ import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.SourceFolder;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
|
||||
import com.intellij.openapi.roots.ui.configuration.CommonContentEntriesEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
|
||||
@@ -145,16 +142,24 @@ public class CompileDriver {
|
||||
|
||||
myGenerationCompilerModuleToOutputDirMap = new HashMap<Pair<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>>();
|
||||
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
final IntermediateOutputCompiler[] generatingCompilers = CompilerManager.getInstance(myProject).getCompilers(IntermediateOutputCompiler.class, myCompilerFilter);
|
||||
if (generatingCompilers.length > 0) {
|
||||
final Module[] allModules = ModuleManager.getInstance(myProject).getModules();
|
||||
final Module[] allModules = ModuleManager.getInstance(myProject).getModules();
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(project);
|
||||
for (Module module : allModules) {
|
||||
for (IntermediateOutputCompiler compiler : generatingCompilers) {
|
||||
for (final Module module : allModules) {
|
||||
final VirtualFile productionOutput = lookupVFile(compiler, module, false);
|
||||
final VirtualFile testOutput = lookupVFile(compiler, module, true);
|
||||
final Pair<IntermediateOutputCompiler, Module> pair = new Pair<IntermediateOutputCompiler, Module>(compiler, module);
|
||||
final Pair<VirtualFile, VirtualFile> outputs = new Pair<VirtualFile, VirtualFile>(productionOutput, testOutput);
|
||||
myGenerationCompilerModuleToOutputDirMap.put(pair, outputs);
|
||||
final VirtualFile productionOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, false));
|
||||
final VirtualFile testOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, true));
|
||||
final Pair<IntermediateOutputCompiler, Module> pair = new Pair<IntermediateOutputCompiler, Module>(compiler, module);
|
||||
final Pair<VirtualFile, VirtualFile> outputs = new Pair<VirtualFile, VirtualFile>(productionOutput, testOutput);
|
||||
myGenerationCompilerModuleToOutputDirMap.put(pair, outputs);
|
||||
}
|
||||
if (config.isAnnotationProcessorsEnabled()) {
|
||||
if (!config.getExcludedModules().contains(module)) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path != null) {
|
||||
lookupVFile(lfs, path); // ensure the file is created and added to VFS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,6 +339,27 @@ public class CompileDriver {
|
||||
return scope;
|
||||
}
|
||||
|
||||
private void attachAnnotationProcessorsOutputDirectories(CompileContextEx context) {
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
final Set<Module> affected = new HashSet<Module>(Arrays.asList(context.getCompileScope().getAffectedModules()));
|
||||
for (Module module : affected) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path == null) {
|
||||
continue;
|
||||
}
|
||||
final VirtualFile vFile = lfs.findFileByPath(path);
|
||||
if (vFile == null) {
|
||||
continue;
|
||||
}
|
||||
if (ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(vFile)) {
|
||||
// no need to add, is already marked as source
|
||||
continue;
|
||||
}
|
||||
context.addScope(new FileSetCompileScope(Collections.singletonList(vFile), new Module[]{module}));
|
||||
context.assignModule(vFile, module, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Key<Long> COMPILATION_START_TIMESTAMP = Key.create("COMPILATION_START_TIMESTAMP");
|
||||
|
||||
private void startup(final CompileScope scope,
|
||||
@@ -365,7 +391,8 @@ public class CompileDriver {
|
||||
compileContext.assignModule(outputs.getFirst(), module, false);
|
||||
compileContext.assignModule(outputs.getSecond(), module, true);
|
||||
}
|
||||
|
||||
attachAnnotationProcessorsOutputDirectories(compileContext);
|
||||
|
||||
compileTask.start(new Runnable() {
|
||||
public void run() {
|
||||
long start = System.currentTimeMillis();
|
||||
@@ -1147,9 +1174,21 @@ public class CompileDriver {
|
||||
|
||||
private Set<File> getAllOutputDirectories() {
|
||||
final Set<File> outputDirs = new OrderedSet<File>((TObjectHashingStrategy<File>)TObjectHashingStrategy.CANONICAL);
|
||||
for (final String path : CompilerPathsEx.getOutputPaths(ModuleManager.getInstance(myProject).getModules())) {
|
||||
final Module[] modules = ModuleManager.getInstance(myProject).getModules();
|
||||
for (final String path : CompilerPathsEx.getOutputPaths(modules)) {
|
||||
outputDirs.add(new File(path));
|
||||
}
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
if (config.isAnnotationProcessorsEnabled()) {
|
||||
for (Module module : modules) {
|
||||
if (!config.getExcludedModules().contains(module)) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path != null) {
|
||||
outputDirs.add(new File(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return outputDirs;
|
||||
}
|
||||
|
||||
@@ -1422,6 +1461,7 @@ public class CompileDriver {
|
||||
context.getProgressIndicator().pushState();
|
||||
|
||||
final boolean[] wereFilesDeleted = new boolean[]{false};
|
||||
boolean traverseRootsProcessed = false;
|
||||
try {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
@@ -1469,15 +1509,17 @@ public class CompileDriver {
|
||||
context.requestRebuildNextTime(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if ((wereFilesDeleted[0] || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
|
||||
final boolean hadUnprocessedTraverseRoots = context.getDependencyCache().hasUnprocessedTraverseRoots();
|
||||
if ((wereFilesDeleted[0] || hadUnprocessedTraverseRoots || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
compiler.compile(context, moduleChunk, VfsUtil.toVirtualFileArray(toCompile), sink);
|
||||
traverseRootsProcessed = hadUnprocessedTraverseRoots != context.getDependencyCache().hasUnprocessedTraverseRoots();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
context.getProgressIndicator().popState();
|
||||
}
|
||||
return !toCompile.isEmpty() || wereFilesDeleted[0];
|
||||
return !toCompile.isEmpty() || traverseRootsProcessed || wereFilesDeleted[0];
|
||||
}
|
||||
|
||||
private static boolean syncOutputDir(final CompileContextEx context, final Collection<Trinity<File, String, Boolean>> toDelete) throws CacheCorruptedException {
|
||||
@@ -1787,8 +1829,10 @@ public class CompileDriver {
|
||||
private boolean validateCompilerConfiguration(final CompileScope scope, boolean checkOutputAndSourceIntersection) {
|
||||
final Module[] scopeModules = scope.getAffectedModules()/*ModuleManager.getInstance(myProject).getModules()*/;
|
||||
final List<String> modulesWithoutOutputPathSpecified = new ArrayList<String>();
|
||||
boolean isProjectCompilePathSpecified = true;
|
||||
final List<String> modulesWithoutJdkAssigned = new ArrayList<String>();
|
||||
final Set<File> nonExistingOutputPaths = new HashSet<File>();
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
|
||||
for (final Module module : scopeModules) {
|
||||
final boolean hasSources = hasSources(module, false);
|
||||
@@ -1830,6 +1874,23 @@ public class CompileDriver {
|
||||
modulesWithoutOutputPathSpecified.add(module.getName());
|
||||
}
|
||||
}
|
||||
if (config.isAnnotationProcessorsEnabled() && !config.getExcludedModules().contains(module)) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path == null) {
|
||||
if (CompilerProjectExtension.getInstance(module.getProject()).getCompilerOutputUrl() == null) {
|
||||
isProjectCompilePathSpecified = false;
|
||||
}
|
||||
else {
|
||||
modulesWithoutOutputPathSpecified.add(module.getName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
final File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
nonExistingOutputPaths.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!modulesWithoutJdkAssigned.isEmpty()) {
|
||||
@@ -1837,6 +1898,17 @@ public class CompileDriver {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isProjectCompilePathSpecified) {
|
||||
final String message = CompilerBundle.message("error.project.output.not.specified");
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
LOG.error(message);
|
||||
}
|
||||
|
||||
Messages.showMessageDialog(myProject, message, CommonBundle.getErrorTitle(), Messages.getErrorIcon());
|
||||
ProjectSettingsService.getInstance(myProject).openProjectSettings();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!modulesWithoutOutputPathSpecified.isEmpty()) {
|
||||
showNotSpecifiedError("error.output.not.specified", modulesWithoutOutputPathSpecified, CommonContentEntriesEditor.NAME);
|
||||
return false;
|
||||
@@ -1880,7 +1952,6 @@ public class CompileDriver {
|
||||
}
|
||||
}
|
||||
final List<Chunk<Module>> chunks = ModuleCompilerUtil.getSortedModuleChunks(myProject, Arrays.asList(scopeModules));
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
for (final Chunk<Module> chunk : chunks) {
|
||||
final Set<Module> chunkModules = chunk.getNodes();
|
||||
if (chunkModules.size() <= 1) {
|
||||
@@ -2071,9 +2142,8 @@ public class CompileDriver {
|
||||
ProjectSettingsService.getInstance(myProject).showModuleConfigurationDialog(moduleNameToSelect, tabNameToSelect, false);
|
||||
}
|
||||
|
||||
private static VirtualFile lookupVFile(final IntermediateOutputCompiler compiler, final Module module, final boolean forTestSources) {
|
||||
final File file = new File(CompilerPaths.getGenerationOutputPath(compiler, module, forTestSources));
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
private static VirtualFile lookupVFile(final LocalFileSystem lfs, final String path) {
|
||||
final File file = new File(path);
|
||||
|
||||
VirtualFile vFile = lfs.findFileByIoFile(file);
|
||||
if (vFile != null) {
|
||||
|
||||
+47
-75
@@ -24,6 +24,7 @@ package com.intellij.compiler.impl.javaCompiler;
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.compiler.CompilerConfigurationImpl;
|
||||
import com.intellij.compiler.CompilerException;
|
||||
import com.intellij.compiler.impl.CompileContextExProxy;
|
||||
import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
|
||||
import com.intellij.compiler.make.CacheCorruptedException;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -33,20 +34,24 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Chunk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AnnotationProcessingCompiler implements SourceProcessingCompiler{
|
||||
public class AnnotationProcessingCompiler implements TranslatingCompiler{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompiler");
|
||||
private final Project myProject;
|
||||
private CompilerConfiguration myConfig;
|
||||
|
||||
public AnnotationProcessingCompiler(Project project) {
|
||||
myProject = project;
|
||||
myConfig = CompilerConfiguration.getInstance(project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -54,74 +59,48 @@ public class AnnotationProcessingCompiler implements SourceProcessingCompiler{
|
||||
return CompilerBundle.message("annotation.processing.compiler.description");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProcessingItem[] getProcessingItems(CompileContext context) {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
if (!config.isAnnotationProcessorsEnabled()) {
|
||||
return ProcessingItem.EMPTY_ARRAY;
|
||||
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
|
||||
if (!myConfig.isAnnotationProcessorsEnabled()) {
|
||||
return false;
|
||||
}
|
||||
return file.getFileType() == StdFileTypes.JAVA && !isExcludedFromAnnotationProcessing(file, context);
|
||||
}
|
||||
|
||||
public void compile(final CompileContext context, final Chunk<Module> moduleChunk, final VirtualFile[] files, OutputSink sink) {
|
||||
if (!myConfig.isAnnotationProcessorsEnabled()) {
|
||||
return;
|
||||
}
|
||||
final VirtualFile[] files = context.getCompileScope().getFiles(StdFileTypes.JAVA, true);
|
||||
final List<ProcessingItem> items = new ArrayList<ProcessingItem>(files.length);
|
||||
final Set<Module> excludedModules = config.getExcludedModules();
|
||||
for (final VirtualFile file : files) {
|
||||
if (excludedModules.size() != 0 && excludedModules.contains(context.getModuleByFile(file))) {
|
||||
continue;
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
final CompileContextEx _context = new CompileContextExProxy((CompileContextEx)context) {
|
||||
public VirtualFile getModuleOutputDirectory(Module module) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
return path != null? lfs.findFileByPath(path) : null;
|
||||
}
|
||||
if (config.isExcludedFromCompilation(file)) {
|
||||
continue;
|
||||
}
|
||||
items.add(new MyProcessingItem(file));
|
||||
}
|
||||
return items.toArray(new ProcessingItem[items.size()]);
|
||||
}
|
||||
|
||||
public ProcessingItem[] process(CompileContext context, ProcessingItem[] items) {
|
||||
final VirtualFile[] files = new VirtualFile[items.length];
|
||||
for (int idx = 0; idx < items.length; idx++) {
|
||||
files[idx] = items[idx].getFile();
|
||||
}
|
||||
compile(context, files);
|
||||
return context.getMessageCount(CompilerMessageCategory.ERROR) == 0? items : ProcessingItem.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
public ValidityState createValidityState(DataInput in) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void compile(final CompileContext context, final VirtualFile[] files) {
|
||||
};
|
||||
final JavacCompiler javacCompiler = getBackEndCompiler();
|
||||
final boolean processorMode = javacCompiler.setAnnotationProcessorMode(true);
|
||||
final Chunk<Module> dummyChunk = new Chunk<Module>(Collections.<Module>emptySet()); // TODO!
|
||||
final BackendCompilerWrapper wrapper = new BackendCompilerWrapper(dummyChunk, myProject, Arrays.asList(files), (CompileContextEx)context, javacCompiler, DummySink.INSTANCE);
|
||||
final BackendCompilerWrapper wrapper = new BackendCompilerWrapper(moduleChunk, myProject, Arrays.asList(files), _context, javacCompiler, sink);
|
||||
try {
|
||||
wrapper.compile();
|
||||
}
|
||||
catch (CompilerException e) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
|
||||
_context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
|
||||
}
|
||||
catch (CacheCorruptedException e) {
|
||||
LOG.info(e);
|
||||
context.requestRebuildNextTime(e.getMessage());
|
||||
_context.requestRebuildNextTime(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
javacCompiler.setAnnotationProcessorMode(processorMode);
|
||||
final Set<VirtualFile> dirsToRefresh = new HashSet<VirtualFile>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Set<Module> modules = new HashSet<Module>();
|
||||
for (VirtualFile file : files) {
|
||||
final Module module = context.getModuleByFile(file);
|
||||
if (module != null) {
|
||||
modules.add(module);
|
||||
for (Module module : moduleChunk.getNodes()) {
|
||||
final VirtualFile out = _context.getModuleOutputDirectory(module);
|
||||
if (out != null) {
|
||||
dirsToRefresh.add(out);
|
||||
}
|
||||
}
|
||||
for (Module module : modules) {
|
||||
dirsToRefresh.add(context.getModuleOutputDirectory(module));
|
||||
dirsToRefresh.add(context.getModuleOutputDirectoryForTests(module));
|
||||
// todo: Some annotation processors put files into the source code. So need to refresh module source roots.
|
||||
// It is an open question whether we shall support such processors
|
||||
//dirsToRefresh.addAll(Arrays.asList(ModuleRootManager.getInstance(module).getSourceRoots()));
|
||||
}
|
||||
}
|
||||
});
|
||||
for (VirtualFile root : dirsToRefresh) {
|
||||
@@ -130,6 +109,21 @@ public class AnnotationProcessingCompiler implements SourceProcessingCompiler{
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExcludedFromAnnotationProcessing(VirtualFile file, CompileContext context) {
|
||||
final Module module = context.getModuleByFile(file);
|
||||
if (module != null) {
|
||||
if (myConfig.getExcludedModules().contains(module)) {
|
||||
return true;
|
||||
}
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
final VirtualFile generationDir = LocalFileSystem.getInstance().findFileByPath(path);
|
||||
if (VfsUtil.isAncestor(generationDir, file, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return myConfig.isExcludedFromCompilation(file);
|
||||
}
|
||||
|
||||
public boolean validateConfiguration(CompileScope scope) {
|
||||
final JavacCompiler compiler = getBackEndCompiler();
|
||||
final boolean previousValue = compiler.setAnnotationProcessorMode(true);
|
||||
@@ -146,26 +140,4 @@ public class AnnotationProcessingCompiler implements SourceProcessingCompiler{
|
||||
return configuration.getJavacCompiler();
|
||||
}
|
||||
|
||||
private static class MyProcessingItem implements ProcessingItem {
|
||||
private final VirtualFile myFile;
|
||||
|
||||
public MyProcessingItem(VirtualFile file) {
|
||||
myFile = file;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile getFile() {
|
||||
return myFile;
|
||||
}
|
||||
|
||||
public ValidityState getValidityState() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DummySink implements TranslatingCompiler.OutputSink {
|
||||
public static final DummySink INSTANCE = new DummySink();
|
||||
public void add(String outputRoot, Collection<TranslatingCompiler.OutputItem> items, VirtualFile[] filesToRecompile) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+414
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author: Eugene Zhuravlev
|
||||
* Date: Jan 24, 2003
|
||||
* Time: 4:25:47 PM
|
||||
*/
|
||||
package com.intellij.compiler.impl.javaCompiler;
|
||||
|
||||
import com.intellij.compiler.CompilerException;
|
||||
import com.intellij.compiler.OutputParser;
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.compiler.make.CacheCorruptedException;
|
||||
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.CompilerBundle;
|
||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||
import com.intellij.openapi.compiler.TranslatingCompiler;
|
||||
import com.intellij.openapi.compiler.ex.CompileContextEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.JavaModuleType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Chunk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class AnnotationProcessorsRunner {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.BackendCompilerWrapper");
|
||||
|
||||
private final BackendCompiler myCompiler;
|
||||
private final Set<VirtualFile> mySuccesfullyCompiledJavaFiles; // VirtualFile
|
||||
|
||||
private final CompileContextEx myCompileContext;
|
||||
private final List<VirtualFile> myFilesToCompile;
|
||||
private final TranslatingCompiler.OutputSink mySink;
|
||||
private final Chunk<Module> myChunk;
|
||||
private final Project myProject;
|
||||
private final Set<VirtualFile> myFilesToRecompile;
|
||||
private final ProjectFileIndex myProjectFileIndex;
|
||||
private long myCompilationDuration = 0L;
|
||||
|
||||
|
||||
public AnnotationProcessorsRunner(Chunk<Module> chunk, @NotNull final Project project,
|
||||
@NotNull List<VirtualFile> filesToCompile,
|
||||
@NotNull CompileContextEx compileContext,
|
||||
@NotNull BackendCompiler compiler, TranslatingCompiler.OutputSink sink) {
|
||||
myChunk = chunk;
|
||||
myProject = project;
|
||||
myCompiler = compiler;
|
||||
myCompileContext = compileContext;
|
||||
myFilesToCompile = filesToCompile;
|
||||
myFilesToRecompile = new HashSet<VirtualFile>(filesToCompile);
|
||||
mySink = sink;
|
||||
myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
mySuccesfullyCompiledJavaFiles = new HashSet<VirtualFile>(filesToCompile.size());
|
||||
}
|
||||
|
||||
public void compile() throws CompilerException, CacheCorruptedException {
|
||||
try {
|
||||
if (!myFilesToCompile.isEmpty()) {
|
||||
final Map<Module, List<VirtualFile>> moduleToFilesMap = buildModuleToFilesMap(myFilesToCompile);
|
||||
myProcessedFilesCount = 0;
|
||||
try {
|
||||
// todo: need special ModuleChunk to be able to filter sources
|
||||
final ModuleChunk chunk = new ModuleChunk(myCompileContext, myChunk, moduleToFilesMap);
|
||||
// TODO: do we really need this for annot. processors?
|
||||
//runTransformingCompilers(chunk);
|
||||
|
||||
setPresentableNameFor(chunk);
|
||||
|
||||
// assuming output dir pointing to source-generated output dir
|
||||
final List<OutputDir> outs = getOutputDirsToCompileTo(chunk);
|
||||
|
||||
for (final OutputDir outputDir : outs) {
|
||||
// todo: proper filtering
|
||||
chunk.setSourcesFilter(outputDir.getKind());
|
||||
doCompile(chunk, outputDir.getPath());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new CompilerException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
throw new CompilerException(CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new CompilerException(e.getMessage(), e);
|
||||
}
|
||||
finally {
|
||||
CompilerUtil.logDuration(myCompiler.getId() + " running", myCompilationDuration);
|
||||
}
|
||||
|
||||
// do not update caches if cancelled because there is a chance that they will be incomplete
|
||||
|
||||
myFilesToRecompile.removeAll(mySuccesfullyCompiledJavaFiles);
|
||||
if (myFilesToRecompile.size() > 0) {
|
||||
mySink.add(null, Collections.<TranslatingCompiler.OutputItem>emptyList(), myFilesToRecompile.toArray(new VirtualFile[myFilesToRecompile.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Module, List<VirtualFile>> buildModuleToFilesMap(final List<VirtualFile> filesToCompile) {
|
||||
if (myChunk.getNodes().size() == 1) {
|
||||
return Collections.singletonMap(myChunk.getNodes().iterator().next(), Collections.unmodifiableList(filesToCompile));
|
||||
}
|
||||
return CompilerUtil.buildModuleToFilesMap(myCompileContext, filesToCompile);
|
||||
}
|
||||
|
||||
|
||||
private void setPresentableNameFor(final ModuleChunk chunk) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Module[] modules = chunk.getModules();
|
||||
StringBuilder moduleName = new StringBuilder(Math.min(128, modules.length * 8));
|
||||
for (int idx = 0; idx < modules.length; idx++) {
|
||||
final Module module = modules[idx];
|
||||
if (idx > 0) {
|
||||
moduleName.append(", ");
|
||||
}
|
||||
moduleName.append(module.getName());
|
||||
if (moduleName.length() > 128 && idx + 1 < modules.length /*name is already too long and seems to grow longer*/) {
|
||||
moduleName.append("...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
myModuleName = moduleName.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<OutputDir> getOutputDirsToCompileTo(ModuleChunk chunk) throws IOException {
|
||||
// todo
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
private class SynchedCompilerParsing extends CompilerParsingThread {
|
||||
|
||||
private SynchedCompilerParsing(Process process, final CompileContext context, OutputParser outputParser, boolean readErrorStream,
|
||||
boolean trimLines) {
|
||||
super(process, outputParser, readErrorStream, trimLines,context);
|
||||
}
|
||||
|
||||
public void setProgressText(String text) {
|
||||
synchronized (lock) {
|
||||
super.setProgressText(text);
|
||||
}
|
||||
}
|
||||
|
||||
public void message(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum) {
|
||||
synchronized (lock) {
|
||||
super.message(category, message, url, lineNum, columnNum);
|
||||
}
|
||||
}
|
||||
|
||||
public void fileProcessed(String path) {
|
||||
synchronized (lock) {
|
||||
sourceFileProcessed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doCompile(@NotNull final ModuleChunk chunk, @NotNull String outputDir) throws IOException {
|
||||
myCompileContext.getProgressIndicator().checkCanceled();
|
||||
|
||||
if (ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
return chunk.getFilesToCompile().isEmpty() ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
}).booleanValue()) {
|
||||
return; // should not invoke javac with empty sources list
|
||||
}
|
||||
|
||||
ModuleType moduleType = chunk.getModules()[0].getModuleType();
|
||||
if (!(chunk.getJdk().getSdkType() instanceof JavaSdkType) &&
|
||||
!(moduleType instanceof JavaModuleType || moduleType.createModuleBuilder() instanceof JavaModuleBuilder)) {
|
||||
// TODO
|
||||
// don't try to compile non-java type module
|
||||
return;
|
||||
}
|
||||
|
||||
int exitValue = 0;
|
||||
try {
|
||||
Process process = myCompiler.launchProcess(chunk, outputDir, myCompileContext);
|
||||
final long compilationStart = System.currentTimeMillis();
|
||||
|
||||
OutputParser errorParser = myCompiler.createErrorParser(outputDir, process);
|
||||
CompilerParsingThread errorParsingThread = errorParser == null
|
||||
? null
|
||||
: new SynchedCompilerParsing(process, myCompileContext, errorParser, true, errorParser.isTrimLines());
|
||||
Future<?> errorParsingThreadFuture = null;
|
||||
if (errorParsingThread != null) {
|
||||
errorParsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(errorParsingThread);
|
||||
}
|
||||
|
||||
OutputParser outputParser = myCompiler.createOutputParser(outputDir);
|
||||
CompilerParsingThread outputParsingThread = outputParser == null
|
||||
? null
|
||||
: new SynchedCompilerParsing(process, myCompileContext, outputParser, false, outputParser.isTrimLines());
|
||||
Future<?> outputParsingThreadFuture = null;
|
||||
if (outputParsingThread != null) {
|
||||
outputParsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(outputParsingThread);
|
||||
}
|
||||
|
||||
try {
|
||||
exitValue = process.waitFor();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
process.destroy();
|
||||
exitValue = process.exitValue();
|
||||
}
|
||||
finally {
|
||||
myCompilationDuration += (System.currentTimeMillis() - compilationStart);
|
||||
if (errorParsingThread != null) {
|
||||
errorParsingThread.setProcessTerminated(true);
|
||||
}
|
||||
if (outputParsingThread != null) {
|
||||
outputParsingThread.setProcessTerminated(true);
|
||||
}
|
||||
joinThread(errorParsingThreadFuture);
|
||||
joinThread(outputParsingThreadFuture);
|
||||
|
||||
registerParsingException(outputParsingThread);
|
||||
registerParsingException(errorParsingThread);
|
||||
assert outputParsingThread == null || !outputParsingThread.processing;
|
||||
assert errorParsingThread == null || !errorParsingThread.processing;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
compileFinished(exitValue, chunk, outputDir);
|
||||
myModuleName = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void joinThread(final Future<?> threadFuture) {
|
||||
if (threadFuture != null) {
|
||||
try {
|
||||
threadFuture.get();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch(ExecutionException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerParsingException(final CompilerParsingThread outputParsingThread) {
|
||||
Throwable error = outputParsingThread == null ? null : outputParsingThread.getError();
|
||||
if (error != null) {
|
||||
String message = error.getMessage();
|
||||
if (error instanceof CacheCorruptedException) {
|
||||
myCompileContext.requestRebuildNextTime(message);
|
||||
}
|
||||
else {
|
||||
myCompileContext.addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void compileFinished(int exitValue, final ModuleChunk chunk, final String outputDir) {
|
||||
if (exitValue != 0 && !myCompileContext.getProgressIndicator().isCanceled() &&
|
||||
myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
|
||||
myCompileContext.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("error.compiler.internal.error", exitValue), null, -1, -1);
|
||||
}
|
||||
|
||||
myCompiler.compileFinished();
|
||||
|
||||
try {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final String outputDirPath = outputDir.replace(File.separatorChar, '/');
|
||||
for (final Module module : chunk.getModules()) {
|
||||
for (final VirtualFile root : chunk.getSourceRoots(module)) {
|
||||
final String packagePrefix = myProjectFileIndex.getPackageNameByDirectory(root);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Building output items for " + root.getPresentableUrl() + "; output dir = " + outputDirPath + "; packagePrefix = \"" + packagePrefix + "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
finally {
|
||||
// todo: refresh dirs her
|
||||
}
|
||||
}
|
||||
|
||||
private volatile int myProcessedFilesCount = 0;
|
||||
private volatile int myClassesCount = 0;
|
||||
private volatile String myModuleName = null;
|
||||
|
||||
private void sourceFileProcessed() {
|
||||
myProcessedFilesCount++;
|
||||
updateStatistics();
|
||||
}
|
||||
|
||||
private void updateStatistics() {
|
||||
final String msg;
|
||||
String moduleName = myModuleName;
|
||||
if (moduleName != null) {
|
||||
msg = CompilerBundle.message("statistics.files.classes.module", myProcessedFilesCount, myClassesCount, moduleName);
|
||||
}
|
||||
else {
|
||||
msg = CompilerBundle.message("statistics.files.classes", myProcessedFilesCount, myClassesCount);
|
||||
}
|
||||
myCompileContext.getProgressIndicator().setText2(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
private void runTransformingCompilers(final ModuleChunk chunk) {
|
||||
final JavaSourceTransformingCompiler[] transformers =
|
||||
CompilerManager.getInstance(myProject).getCompilers(JavaSourceTransformingCompiler.class);
|
||||
if (transformers.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Running transforming compilers...");
|
||||
}
|
||||
final Module[] modules = chunk.getModules();
|
||||
for (final JavaSourceTransformingCompiler transformer : transformers) {
|
||||
final Map<VirtualFile, VirtualFile> originalToCopyFileMap = new HashMap<VirtualFile, VirtualFile>();
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
application.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
for (final Module module : modules) {
|
||||
List<VirtualFile> filesToCompile = chunk.getFilesToCompile(module);
|
||||
for (final VirtualFile file : filesToCompile) {
|
||||
if (transformer.isTransformable(file)) {
|
||||
application.runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
VirtualFile fileCopy = createFileCopy(getTempDir(module), file);
|
||||
originalToCopyFileMap.put(file, fileCopy);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// skip it
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, myCompileContext.getProgressIndicator().getModalityState());
|
||||
|
||||
// do actual transform
|
||||
for (final Module module : modules) {
|
||||
final List<VirtualFile> filesToCompile = chunk.getFilesToCompile(module);
|
||||
for (int j = 0; j < filesToCompile.size(); j++) {
|
||||
final VirtualFile file = filesToCompile.get(j);
|
||||
VirtualFile fileCopy = originalToCopyFileMap.get(file);
|
||||
if (fileCopy != null) {
|
||||
final boolean ok = transformer.transform(myCompileContext, fileCopy, file);
|
||||
if (ok) {
|
||||
chunk.substituteWithTransformedVersion(module, j, fileCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private VirtualFile createFileCopy(VirtualFile tempDir, final VirtualFile file) throws IOException {
|
||||
final String fileName = file.getName();
|
||||
if (tempDir.findChild(fileName) != null) {
|
||||
int idx = 0;
|
||||
while (true) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
final String dirName = "dir" + idx++;
|
||||
final VirtualFile dir = tempDir.findChild(dirName);
|
||||
if (dir == null) {
|
||||
tempDir = tempDir.createChildDirectory(this, dirName);
|
||||
break;
|
||||
}
|
||||
if (dir.findChild(fileName) == null) {
|
||||
tempDir = dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return VfsUtil.copyFile(this, file, tempDir);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class ModuleChunk extends Chunk<Module> {
|
||||
return convertToStringPath(cpFiles);
|
||||
}
|
||||
|
||||
private String convertToStringPath(final OrderedSet<VirtualFile> cpFiles) {
|
||||
private static String convertToStringPath(final OrderedSet<VirtualFile> cpFiles) {
|
||||
final StringBuilder classpathBuffer = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
for (final VirtualFile file : cpFiles) {
|
||||
|
||||
-3
@@ -310,9 +310,6 @@ public class JavacCompiler extends ExternalCompiler {
|
||||
}
|
||||
}
|
||||
}
|
||||
//additionalOptions.add("-processor");
|
||||
//additionalOptions.add("CheckNamesProcessor");
|
||||
//additionalOptions.add("org.apache.openjpa.persistence.meta.AnnotationProcessor6");
|
||||
}
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
@NonNls String token = tokenizer.nextToken();
|
||||
|
||||
@@ -118,6 +118,10 @@ public class DependencyCache {
|
||||
myTraverseRoots.clear();
|
||||
}
|
||||
|
||||
public boolean hasUnprocessedTraverseRoots() {
|
||||
return !myTraverseRoots.isEmpty();
|
||||
}
|
||||
|
||||
public void markSourceRemoved(int qName) {
|
||||
myClassesWithSourceRemoved.add(qName);
|
||||
}
|
||||
|
||||
+2
-12
@@ -1,7 +1,6 @@
|
||||
package com.intellij.compiler.options;
|
||||
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.ide.util.ElementsChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooser;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -16,7 +15,6 @@ import com.intellij.ui.TableUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.ItemRemovable;
|
||||
import com.intellij.util.ui.Table;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.TitledBorder;
|
||||
@@ -38,7 +36,7 @@ import java.util.*;
|
||||
* Date: Oct 5, 2009
|
||||
*/
|
||||
public class AnnotationProcessorsConfigurable implements Configurable{
|
||||
private ElementsChooser<Module> myModulesChooser;
|
||||
private ProcessedModulesChooser myModulesChooser;
|
||||
private final Project myProject;
|
||||
private JRadioButton myRbClasspath;
|
||||
private JRadioButton myRbProcessorsPath;
|
||||
@@ -107,15 +105,7 @@ public class AnnotationProcessorsConfigurable implements Configurable{
|
||||
processorTablePanel.add(buttons, BorderLayout.EAST);
|
||||
processorTablePanel.setPreferredSize(new Dimension(processorTablePanel.getPreferredSize().width, 50));
|
||||
|
||||
myModulesChooser = new ElementsChooser<Module>(true) {
|
||||
protected String getItemText(@NotNull Module module) {
|
||||
return module.getName() + " (" + FileUtil.toSystemDependentName(module.getModuleFilePath()) + ")";
|
||||
}
|
||||
|
||||
protected Icon getItemIcon(Module module) {
|
||||
return module.getModuleType().getNodeIcon(false);
|
||||
}
|
||||
};
|
||||
myModulesChooser = new ProcessedModulesChooser();
|
||||
myModulesChooser.setBorder(BorderFactory.createTitledBorder("Processed Modules"));
|
||||
|
||||
mainPanel.add(myCbEnableProcessing, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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 com.intellij.compiler.options;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.SpeedSearchBase;
|
||||
import com.intellij.ui.TableUtil;
|
||||
import com.intellij.util.ui.Table;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class ProcessedModulesChooser extends JPanel {
|
||||
private Table myTable = null;
|
||||
private MyTableModel myTableModel = null;
|
||||
private boolean myColorUnmarkedElements = true;
|
||||
private final Map<Module, Boolean> myDisabledMap = new HashMap<Module, Boolean>();
|
||||
|
||||
public ProcessedModulesChooser() {
|
||||
super(new BorderLayout());
|
||||
|
||||
myTableModel = new MyTableModel(true);
|
||||
myTable = new Table(myTableModel);
|
||||
myTable.setShowGrid(false);
|
||||
myTable.setIntercellSpacing(new Dimension(0, 0));
|
||||
myTable.setTableHeader(null);
|
||||
myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
myTable.setColumnSelectionAllowed(false);
|
||||
JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
|
||||
pane.setPreferredSize(new Dimension(100, 155));
|
||||
int width = new JCheckBox().getPreferredSize().width;
|
||||
TableColumnModel columnModel = myTable.getColumnModel();
|
||||
|
||||
TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
|
||||
checkMarkColumn.setPreferredWidth(width);
|
||||
checkMarkColumn.setMaxWidth(width);
|
||||
checkMarkColumn.setCellRenderer(new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class)));
|
||||
columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
|
||||
|
||||
add(pane, BorderLayout.CENTER);
|
||||
myTable.registerKeyboardAction(
|
||||
new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final int[] selectedRows = myTable.getSelectedRows();
|
||||
boolean currentlyMarked = true;
|
||||
for (int selectedRow : selectedRows) {
|
||||
currentlyMarked = myTableModel.isElementMarked(selectedRow);
|
||||
if (!currentlyMarked) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
myTableModel.setMarked(selectedRows, !currentlyMarked);
|
||||
}
|
||||
},
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
|
||||
JComponent.WHEN_FOCUSED
|
||||
);
|
||||
|
||||
final SpeedSearchBase<Table> speedSearch = new SpeedSearchBase<Table>(myTable) {
|
||||
public int getSelectedIndex() {
|
||||
return myTable.getSelectedRow();
|
||||
}
|
||||
|
||||
public Object[] getAllElements() {
|
||||
final int count = myTableModel.getRowCount();
|
||||
Object[] elements = new Object[count];
|
||||
for (int idx = 0; idx < count; idx++) {
|
||||
elements[idx] = myTableModel.getElementAt(idx);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public String getElementText(Object element) {
|
||||
return ((Module)element).getName() + " (" + FileUtil.toSystemDependentName(((Module)element).getModuleFilePath()) + ")";
|
||||
}
|
||||
|
||||
public void selectElement(Object element, String selectedText) {
|
||||
final int count = myTableModel.getRowCount();
|
||||
for (int row = 0; row < count; row++) {
|
||||
if (element.equals(myTableModel.getElementAt(row))) {
|
||||
myTable.getSelectionModel().setSelectionInterval(row, row);
|
||||
TableUtil.scrollSelectionToVisible(myTable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
speedSearch.setComparator(new SpeedSearchBase.SpeedSearchComparator(false));
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
myTableModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void refresh(Module element) {
|
||||
final int row = myTableModel.getElementRow(element);
|
||||
if (row >= 0) {
|
||||
myTableModel.fireTableRowsUpdated(row, row);
|
||||
}
|
||||
}
|
||||
|
||||
private int[] mySavedSelection = null;
|
||||
public void saveSelection() {
|
||||
mySavedSelection = myTable.getSelectedRows();
|
||||
}
|
||||
|
||||
public void restoreSelection() {
|
||||
if (mySavedSelection != null) {
|
||||
TableUtil.selectRows(myTable, mySavedSelection);
|
||||
mySavedSelection = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void addElement(Module element, final boolean isMarked) {
|
||||
myTableModel.addElement(element, isMarked);
|
||||
selectRow(myTableModel.getRowCount() - 1);
|
||||
myTable.requestFocus();
|
||||
}
|
||||
|
||||
public boolean isElementMarked(Module element) {
|
||||
final int elementRow = myTableModel.getElementRow(element);
|
||||
return myTableModel.isElementMarked(elementRow);
|
||||
}
|
||||
|
||||
public void setElementMarked(Module element, boolean marked) {
|
||||
final int elementRow = myTableModel.getElementRow(element);
|
||||
myTableModel.setMarked(elementRow, marked);
|
||||
}
|
||||
|
||||
|
||||
public void removeElement(Module element) {
|
||||
final int elementRow = myTableModel.getElementRow(element);
|
||||
if (elementRow < 0) {
|
||||
return; // no such element
|
||||
}
|
||||
final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
|
||||
|
||||
myTableModel.removeElement(element);
|
||||
|
||||
if (wasSelected) {
|
||||
final int rowCount = myTableModel.getRowCount();
|
||||
if (rowCount > 0) {
|
||||
selectRow(elementRow % rowCount);
|
||||
}
|
||||
else {
|
||||
myTable.getSelectionModel().clearSelection();
|
||||
}
|
||||
}
|
||||
myTable.requestFocus();
|
||||
}
|
||||
|
||||
public void removeAllElements() {
|
||||
myTableModel.removeAllElements();
|
||||
myTable.getSelectionModel().clearSelection();
|
||||
}
|
||||
|
||||
private void selectRow(final int row) {
|
||||
myTable.getSelectionModel().setSelectionInterval(row, row);
|
||||
myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Module getSelectedElement() {
|
||||
final int selectedRow = getSelectedElementRow();
|
||||
return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
|
||||
}
|
||||
|
||||
public int getSelectedElementRow() {
|
||||
return myTable.getSelectedRow();
|
||||
}
|
||||
|
||||
public List<Module> getSelectedElements() {
|
||||
final List<Module> elements = new ArrayList<Module>();
|
||||
final int[] selectedRows = myTable.getSelectedRows();
|
||||
for (int selectedRow : selectedRows) {
|
||||
if (selectedRow < 0) {
|
||||
continue;
|
||||
}
|
||||
elements.add(myTableModel.getElementAt(selectedRow));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public void selectElements(Collection<? extends Module> elements) {
|
||||
if (elements.size() == 0) {
|
||||
myTable.clearSelection();
|
||||
return;
|
||||
}
|
||||
final int[] rows = getElementsRows(elements);
|
||||
TableUtil.selectRows(myTable, rows);
|
||||
TableUtil.scrollSelectionToVisible(myTable);
|
||||
myTable.requestFocus();
|
||||
}
|
||||
|
||||
private int[] getElementsRows(final Collection<? extends Module> elements) {
|
||||
final int[] rows = new int[elements.size()];
|
||||
int index = 0;
|
||||
for (final Module element : elements) {
|
||||
rows[index++] = myTableModel.getElementRow(element);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
public void markElements(Collection<Module> elements) {
|
||||
myTableModel.setMarked(getElementsRows(elements), true);
|
||||
}
|
||||
|
||||
public List<Module> getMarkedElements() {
|
||||
final int count = myTableModel.getRowCount();
|
||||
List<Module> elements = new ArrayList<Module>();
|
||||
for (int idx = 0; idx < count; idx++) {
|
||||
final Module element = myTableModel.getElementAt(idx);
|
||||
if (myTableModel.isElementMarked(idx)) {
|
||||
elements.add(element);
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
public void sort(Comparator<Module> comparator) {
|
||||
myTableModel.sort(comparator);
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
myTable.setRowSelectionAllowed(enabled);
|
||||
myTableModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void stopEditing() {
|
||||
TableCellEditor editor = myTable.getCellEditor();
|
||||
if (editor != null) {
|
||||
editor.stopCellEditing();
|
||||
}
|
||||
}
|
||||
|
||||
public JComponent getComponent() {
|
||||
return myTable;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myTableModel.clear();
|
||||
}
|
||||
|
||||
public int getElementCount() {
|
||||
return myTableModel.getRowCount();
|
||||
}
|
||||
|
||||
public Module getElementAt(int row) {
|
||||
return myTableModel.getElementAt(row);
|
||||
}
|
||||
|
||||
public void disableElement(Module element) {
|
||||
myDisabledMap.put(element, Boolean.TRUE);
|
||||
}
|
||||
|
||||
private final class MyTableModel extends AbstractTableModel {
|
||||
private final List<Module> myElements = new ArrayList<Module>();
|
||||
private final Map<Module, Boolean> myMarkedMap = new HashMap<Module, Boolean>();
|
||||
public final int CHECK_MARK_COLUM_INDEX;
|
||||
public final int ELEMENT_COLUMN_INDEX;
|
||||
private final boolean myElementsCanBeMarked;
|
||||
|
||||
public MyTableModel(final boolean elementsCanBeMarked) {
|
||||
myElementsCanBeMarked = elementsCanBeMarked;
|
||||
if (elementsCanBeMarked) {
|
||||
CHECK_MARK_COLUM_INDEX = 0;
|
||||
ELEMENT_COLUMN_INDEX = 1;
|
||||
}
|
||||
else {
|
||||
CHECK_MARK_COLUM_INDEX = -1;
|
||||
ELEMENT_COLUMN_INDEX = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void sort(Comparator<Module> comparator) {
|
||||
Collections.sort(myElements, comparator);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public Module getElementAt(int index) {
|
||||
return myElements.get(index);
|
||||
}
|
||||
|
||||
public boolean isElementMarked(int index) {
|
||||
final Module element = myElements.get(index);
|
||||
final Boolean isMarked = myMarkedMap.get(element);
|
||||
return isMarked.booleanValue();
|
||||
}
|
||||
|
||||
void addElement(Module element, boolean isMarked) {
|
||||
myElements.add(element);
|
||||
myMarkedMap.put(element, isMarked? Boolean.TRUE : Boolean.FALSE);
|
||||
int row = myElements.size() - 1;
|
||||
fireTableRowsInserted(row, row);
|
||||
}
|
||||
|
||||
void addElements(List<Module> elements, boolean isMarked) {
|
||||
if (elements == null || elements.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (final Module element : elements) {
|
||||
myElements.add(element);
|
||||
myMarkedMap.put(element, isMarked ? Boolean.TRUE : Boolean.FALSE);
|
||||
}
|
||||
fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
|
||||
}
|
||||
|
||||
public void removeElement(Module element) {
|
||||
final boolean reallyRemoved = myElements.remove(element);
|
||||
if (reallyRemoved) {
|
||||
myMarkedMap.remove(element);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void changeElementRow(Module element, int row) {
|
||||
final boolean reallyRemoved = myElements.remove(element);
|
||||
if (reallyRemoved) {
|
||||
myElements.add(row, element);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int getElementRow(Module element) {
|
||||
return myElements.indexOf(element);
|
||||
}
|
||||
|
||||
public void removeAllElements() {
|
||||
myElements.clear();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void removeRows(int[] rows) {
|
||||
final List<Module> toRemove = new ArrayList<Module>();
|
||||
for (int row : rows) {
|
||||
final Module element = myElements.get(row);
|
||||
toRemove.add(element);
|
||||
myMarkedMap.remove(element);
|
||||
}
|
||||
myElements.removeAll(toRemove);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return myElements.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return myElementsCanBeMarked? 2 : 1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
Module element = myElements.get(rowIndex);
|
||||
if (columnIndex == ELEMENT_COLUMN_INDEX) {
|
||||
return element;
|
||||
}
|
||||
if (columnIndex == CHECK_MARK_COLUM_INDEX) {
|
||||
return myMarkedMap.get(element);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (columnIndex == CHECK_MARK_COLUM_INDEX) {
|
||||
setMarked(rowIndex, ((Boolean)aValue).booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void setMarked(int rowIndex, final boolean marked) {
|
||||
final Module element = myElements.get(rowIndex);
|
||||
final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
|
||||
myMarkedMap.put(element, newValue);
|
||||
fireTableRowsUpdated(rowIndex, rowIndex);
|
||||
}
|
||||
|
||||
private void setMarked(int[] rows, final boolean marked) {
|
||||
if (rows == null || rows.length == 0) {
|
||||
return;
|
||||
}
|
||||
int firstRow = Integer.MAX_VALUE;
|
||||
int lastRow = Integer.MIN_VALUE;
|
||||
final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
|
||||
for (final int row : rows) {
|
||||
final Module element = myElements.get(row);
|
||||
myMarkedMap.put(element, newValue);
|
||||
firstRow = Math.min(firstRow, row);
|
||||
lastRow = Math.max(lastRow, row);
|
||||
}
|
||||
fireTableRowsUpdated(firstRow, lastRow);
|
||||
}
|
||||
|
||||
public Class getColumnClass(int columnIndex) {
|
||||
if (columnIndex == CHECK_MARK_COLUM_INDEX) {
|
||||
return Boolean.class;
|
||||
}
|
||||
return super.getColumnClass(columnIndex);
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
if (!ProcessedModulesChooser.this.isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
|
||||
return false;
|
||||
}
|
||||
final Module o = (Module)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
|
||||
return myDisabledMap.get(o) == null;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myElements.clear();
|
||||
myMarkedMap.clear();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
final Color color = UIUtil.getTableFocusCellBackground();
|
||||
Component component;
|
||||
Module module = (Module)value;
|
||||
try {
|
||||
UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
|
||||
component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
setText(module != null ? module.getName() + " (" + FileUtil.toSystemDependentName(module.getModuleFilePath()) + ")" : "");
|
||||
if (component instanceof JLabel) {
|
||||
((JLabel)component).setBorder(noFocusBorder);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
|
||||
}
|
||||
final MyTableModel model = (MyTableModel)table.getModel();
|
||||
component.setEnabled(ProcessedModulesChooser.this.isEnabled() && (myColorUnmarkedElements? model.isElementMarked(row) : true));
|
||||
if (component instanceof JLabel) {
|
||||
final Icon icon = module != null ? module.getModuleType().getNodeIcon(false) : null;
|
||||
JLabel label = (JLabel)component;
|
||||
label.setIcon(icon);
|
||||
label.setDisabledIcon(icon);
|
||||
}
|
||||
component.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
private class CheckMarkColumnCellRenderer implements TableCellRenderer {
|
||||
private final TableCellRenderer myDelegate;
|
||||
|
||||
public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
component.setEnabled(ProcessedModulesChooser.this.isEnabled());
|
||||
if (component instanceof JComponent) {
|
||||
((JComponent)component).setBorder(null);
|
||||
}
|
||||
return component;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package com.intellij.compiler;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -59,4 +60,13 @@ public abstract class CompilerConfiguration {
|
||||
public abstract Set<Module> getExcludedModules();
|
||||
|
||||
public abstract void setExcludedModules(Collection<Module> modules);
|
||||
|
||||
public abstract boolean isStoreGenerateSourcesUnderModuleContent(Module module);
|
||||
|
||||
public abstract void setStoreGenerateSourcesUnderModuleContent(boolean storeGenerateSourcesUnderModuleContent);
|
||||
|
||||
@NotNull
|
||||
public abstract String getGeneratedDirName();
|
||||
|
||||
public abstract void setGeneratedDirName(String generatedDirName);
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.compiler;
|
||||
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.ide.highlighter.ProjectFileType;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -23,6 +24,8 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.CompilerModuleExtension;
|
||||
import com.intellij.openapi.roots.CompilerProjectExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -33,6 +36,8 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@@ -41,6 +46,11 @@ import java.util.Locale;
|
||||
public class CompilerPaths {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.compiler.CompilerPaths");
|
||||
private static volatile String ourSystemPath;
|
||||
private static final Comparator<String> URLS_COMPARATOR = new Comparator<String>() {
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a directory
|
||||
@@ -180,6 +190,27 @@ public class CompilerPaths {
|
||||
return outPathUrl != null? VirtualFileManager.extractPath(outPathUrl) : null;
|
||||
}
|
||||
|
||||
public static String getAnnotationProcessorsGenerationPath(Module module) {
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(module.getProject());
|
||||
|
||||
if (config.isStoreGenerateSourcesUnderModuleContent(module)) {
|
||||
final String[] roots = ModuleRootManager.getInstance(module).getContentRootUrls();
|
||||
if (roots.length == 0) {
|
||||
return null;
|
||||
}
|
||||
if (roots.length > 1) {
|
||||
Arrays.sort(roots, URLS_COMPARATOR);
|
||||
}
|
||||
return VirtualFileManager.extractPath(roots[0]) + "/" + config.getGeneratedDirName();
|
||||
}
|
||||
|
||||
final String url = CompilerProjectExtension.getInstance(module.getProject()).getCompilerOutputUrl();
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
return VirtualFileManager.extractPath(url) + "/generated/" + module.getName().toLowerCase();
|
||||
}
|
||||
|
||||
@NonNls
|
||||
public static String getGenerationOutputPath(IntermediateOutputCompiler compiler, Module module, final boolean forTestSources) {
|
||||
final String generatedCompilerDirectoryPath = getGeneratedDataDirectory(module.getProject(), compiler).getPath();
|
||||
|
||||
+10
-1
@@ -21,11 +21,11 @@ import com.intellij.ide.util.projectWizard.JdkChooserPanel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.JdkOrderEntry;
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -38,6 +38,15 @@ public class IdeaProjectSettingsService extends ProjectSettingsService {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public void openProjectSettings() {
|
||||
final ProjectStructureConfigurable config = ProjectStructureConfigurable.getInstance(myProject);
|
||||
ShowSettingsUtil.getInstance().editConfigurable(myProject, config, new Runnable() {
|
||||
public void run() {
|
||||
config.selectProjectGeneralSettings(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void openModuleSettings(final Module module) {
|
||||
ModulesConfigurator.showDialog(myProject, module.getName(), null, false);
|
||||
}
|
||||
|
||||
+5
@@ -338,6 +338,11 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
|
||||
Place.queryFurther(mySelectedConfigurable, place);
|
||||
}
|
||||
|
||||
public ActionCallback selectProjectGeneralSettings(final boolean requestFocus) {
|
||||
Place place = new Place().putPath(CATEGORY, myProjectConfig);
|
||||
return navigateTo(place, requestFocus);
|
||||
}
|
||||
|
||||
public ActionCallback select(@Nullable final String moduleToSelect, String tab, final boolean requestFocus) {
|
||||
Place place = new Place().putPath(CATEGORY, myModulesConfig);
|
||||
if (moduleToSelect != null) {
|
||||
|
||||
Reference in New Issue
Block a user