support for resource directories: enable java-specific actions only for directories...
[idea/community.git] / java / compiler / impl / src / com / intellij / compiler / actions / CompileAction.java
1 /*
2  * Copyright 2000-2012 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.compiler.actions;
17
18 import com.intellij.compiler.CompilerConfiguration;
19 import com.intellij.idea.ActionsBundle;
20 import com.intellij.openapi.actionSystem.*;
21 import com.intellij.openapi.compiler.CompilerBundle;
22 import com.intellij.openapi.compiler.CompilerManager;
23 import com.intellij.openapi.fileTypes.FileType;
24 import com.intellij.openapi.module.Module;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.roots.ProjectFileIndex;
27 import com.intellij.openapi.roots.ProjectRootManager;
28 import com.intellij.openapi.util.text.StringUtil;
29 import com.intellij.openapi.vfs.VfsUtil;
30 import com.intellij.openapi.vfs.VirtualFile;
31 import com.intellij.packaging.artifacts.Artifact;
32 import com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder;
33 import com.intellij.psi.*;
34
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.List;
38
39 public class CompileAction extends CompileActionBase {
40   protected void doAction(DataContext dataContext, Project project) {
41     final Module module = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
42     if (module != null) {
43       CompilerManager.getInstance(project).compile(module, null);
44     }
45     else {
46       VirtualFile[] files = getCompilableFiles(project, PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext));
47       if (files.length > 0) {
48         CompilerManager.getInstance(project).compile(files, null);
49       }
50     }
51
52   }
53
54   public void update(AnActionEvent event) {
55     super.update(event);
56     Presentation presentation = event.getPresentation();
57     if (!presentation.isEnabled()) {
58       return;
59     }
60     DataContext dataContext = event.getDataContext();
61
62     presentation.setText(ActionsBundle.actionText(IdeActions.ACTION_COMPILE));
63     presentation.setVisible(true);
64
65     Project project = PlatformDataKeys.PROJECT.getData(dataContext);
66     if (project == null) {
67       presentation.setEnabled(false);
68       return;
69     }
70
71     CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(project);
72     final Module module = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
73
74     final VirtualFile[] files = getCompilableFiles(project, PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext));
75     if (module == null && files.length == 0) {
76       presentation.setEnabled(false);
77       presentation.setVisible(!ActionPlaces.isPopupPlace(event.getPlace()));
78       return;
79     }
80
81     String elementDescription = null;
82     if (module != null) {
83       elementDescription = CompilerBundle.message("action.compile.description.module", module.getName());
84     }
85     else {
86       PsiPackage aPackage = null;
87       if (files.length == 1) {
88         final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(files[0]);
89         if (directory != null) {
90           aPackage = JavaDirectoryService.getInstance().getPackage(directory);
91         }
92       }
93       else {
94         PsiElement element = LangDataKeys.PSI_ELEMENT.getData(dataContext);
95         if (element instanceof PsiPackage) {
96           aPackage = (PsiPackage)element;
97         }
98       }
99
100       if (aPackage != null) {
101         String name = aPackage.getQualifiedName();
102         if (name.length() == 0) {
103           //noinspection HardCodedStringLiteral
104           name = "<default>";
105         }
106         elementDescription = "'" + name + "'";
107       }
108       else if (files.length == 1) {
109         final VirtualFile file = files[0];
110         FileType fileType = file.getFileType();
111         if (CompilerManager.getInstance(project).isCompilableFileType(fileType) || isCompilableResourceFile(project, compilerConfiguration, file)) {
112           elementDescription = "'" + file.getName() + "'";
113         }
114         else {
115           if (!ActionPlaces.MAIN_MENU.equals(event.getPlace())) {
116             // the action should be invisible in popups for non-java files
117             presentation.setEnabled(false);
118             presentation.setVisible(false);
119             return;
120           }
121         }
122       }
123       else {
124         elementDescription = CompilerBundle.message("action.compile.description.selected.files");
125       }
126     }
127
128     if (elementDescription == null) {
129       presentation.setEnabled(false);
130       return;
131     }
132
133     presentation.setText(createPresentationText(elementDescription), true);
134     presentation.setEnabled(true);
135   }
136
137   private static String createPresentationText(String elementDescription) {
138     StringBuffer buffer = new StringBuffer(40);
139     buffer.append(ActionsBundle.actionText(IdeActions.ACTION_COMPILE)).append(" ");
140     int length = elementDescription.length();
141     if (length > 23) {
142       if (StringUtil.startsWithChar(elementDescription, '\'')) {
143         buffer.append("'");
144       }
145       buffer.append("...");
146       buffer.append(elementDescription.substring(length - 20, length));
147     }
148     else {
149       buffer.append(elementDescription);
150     }
151     return buffer.toString();
152   }
153
154   private static VirtualFile[] getCompilableFiles(Project project, VirtualFile[] files) {
155     if (files == null || files.length == 0) {
156       return VirtualFile.EMPTY_ARRAY;
157     }
158     final PsiManager psiManager = PsiManager.getInstance(project);
159     final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(project);
160     final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
161     final CompilerManager compilerManager = CompilerManager.getInstance(project);
162     final List<VirtualFile> filesToCompile = new ArrayList<VirtualFile>();
163     for (final VirtualFile file : files) {
164       if (!fileIndex.isInSourceContent(file)) {
165         continue;
166       }
167       if (!file.isInLocalFileSystem()) {
168         continue;
169       }
170       if (file.isDirectory()) {
171         final PsiDirectory directory = psiManager.findDirectory(file);
172         if (directory == null || JavaDirectoryService.getInstance().getPackage(directory) == null) {
173           continue;
174         }
175       }
176       else {
177         FileType fileType = file.getFileType();
178         if (!(compilerManager.isCompilableFileType(fileType) || isCompilableResourceFile(project, compilerConfiguration, file))) {
179           continue;
180         }
181       }
182       filesToCompile.add(file);
183     }
184     return VfsUtil.toVirtualFileArray(filesToCompile);
185   }
186
187   private static boolean isCompilableResourceFile(final Project project, final CompilerConfiguration compilerConfiguration, final VirtualFile file) {
188     if (!compilerConfiguration.isResourceFile(file)) {
189       return false;
190     }
191     final Collection<? extends Artifact> artifacts = ArtifactBySourceFileFinder.getInstance(project).findArtifacts(file);
192     return artifacts.isEmpty();
193   }
194 }