Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Dmitry Boulytchev
2012-02-08 17:34:26 +04:00
110 changed files with 2382 additions and 1050 deletions
+2 -1
View File
@@ -9,7 +9,8 @@
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml" filepath="$PROJECT_DIR$/plugins/IntentionPowerPak/IntentionPowerPackPlugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/android/android.iml" filepath="$PROJECT_DIR$/plugins/android/android.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/android/android.iml" filepath="$PROJECT_DIR$/plugins/android/android.iml" group="plugins/Android" />
<module fileurl="file://$PROJECT_DIR$/plugins/android/rt/android-rt.iml" filepath="$PROJECT_DIR$/plugins/android/rt/android-rt.iml" group="plugins/Android" />
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" />
+2
View File
@@ -364,6 +364,8 @@ public def layoutCommunityPlugins(String home) {
include(name: "**/*.jar")
exclude(name: "**/ddmlib_1.jar")
}
jar("android_rt.jar") {module("android-rt")}
}
}
}
+5 -4
View File
@@ -190,9 +190,9 @@ libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as licens
libraryLicense(name: "JCIP Annotations", libraryName: "jcip", license: "Creative Commons Attribution License", url: "http://www.jcip.net", licenseUrl: "http://creativecommons.org/licenses/by/2.5")
libraryLicense(name: "JDOM", version: "1.1 (with patches by JetBrains)", license: "modified Apache", url: "http://www.jdom.org/", licenseUrl: "http://www.jdom.org/docs/faq.html#a0030")
libraryLicense(name: "jgit-1.1.0", version: "1.1.0.201109151100", license: "EDL/BSD", url: "http://www.eclipse.org/jgit/", licenseUrl: "http://www.eclipse.org/org/documents/edl-v10.php", attachedTo: "git4idea")
libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "CVS snapshot as of 5 May 2006", license: "BSD ", url: "http://www.jgoodies.com/freeware/forms/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JGoodies Looks", attachedTo: "platform-impl", version: "2.4.2", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JGoodies Common", attachedTo: "platform-impl", version: "1.2.1", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "1.1-preview 2006-05-04 11:55:37", license: "BSD ", url: "http://www.jgoodies.com/freeware/forms/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JGoodies Looks", libraryName: "jgoodies-looks", version: "2.4.2", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JGoodies Common", libraryName: "jgoodies-common", version: "1.2.1", license: "BSD ", url: "http://www.jgoodies.com/freeware/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JNA", libraryName: "jna", version: "3.2.4", license: "LGPL 2.1", url: "https://jna.dev.java.net/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
libraryLicense(name: "JNA", libraryName: "jna.jar", version: "3.2.7", license: "LGPL 2.1", url: "https://jna.dev.java.net/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
libraryLicense(name: "JSch", libraryName: "JSch", version: "0.1.44", license: "BSD", url: "http://www.jcraft.com/jsch/", licenseUrl: "http://www.jcraft.com/jsch/LICENSE.txt")
@@ -238,4 +238,5 @@ libraryLicense(name: "Kryo", libraryName: "Kryo", version: "1.04", license: "New
jetbrainsLibrary("JPS")
jetbrainsLibrary("Maven Embedder")
jetbrainsLibrary("tcServiceMessages")
jetbrainsLibrary("optimizedFileManager.jar")
jetbrainsLibrary("optimizedFileManager.jar")
jetbrainsLibrary("RunTime")
@@ -51,8 +51,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBoxWithWidePopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.CaptionPanel;
import com.intellij.ui.PopupHandler;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.Alarm;
import com.sun.jdi.ObjectCollectedException;
@@ -114,6 +116,8 @@ public class FramesPanel extends UpdatableDebuggerView {
final ActionToolbar toolbar = createToolbar();
Wrapper threads = new Wrapper();
CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_COLOR, 0, 0, 1, 0);
threads.setBorder(border);
threads.add(toolbar.getComponent(), BorderLayout.EAST);
threads.add(myThreadsCombo, BorderLayout.CENTER);
add(threads, BorderLayout.NORTH);
@@ -43,10 +43,10 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.AnActionButtonRunnable;
import com.intellij.ui.ListenerUtil;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.*;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import javax.swing.*;
import java.awt.*;
@@ -218,13 +218,20 @@ public class MainWatchPanel extends WatchPanel implements DataProvider {
executeAction(DebuggerActions.NEW_WATCH, tree);
}
});
// TODO[den]: add "Add to watches action"
// TODO[den]: add "Add to watches action" on Mac
if (!SystemInfo.isMac) {
decorator.addExtraAction(AnActionButton.fromAction(ActionManager.getInstance().getAction(XDebuggerActions.ADD_TO_WATCH)));
}
decorator.setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
executeAction(DebuggerActions.REMOVE_WATCH, tree);
}
});
CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_COLOR,
SystemInfo.isMac ? 1 : 0, 0,
SystemInfo.isMac ? 0 : 1, 0);
decorator.setToolbarBorder(border);
final JPanel panel = decorator.createPanel();
panel.setBorder(null);
return panel;
@@ -640,9 +640,9 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
}
private static boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
final PsiClassImpl containingClass = (PsiClassImpl)member.getContainingClass();
if (containingClass == null) return true;
final PsiMethod valuesMethod = containingClass.getValuesMethod();
final PsiClass containingClass = member.getContainingClass();
if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
if (valuesMethod == null) return true;
return isMethodReferenced(valuesMethod, progress, helper);
}
@@ -34,6 +34,8 @@ import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author ven
*/
@@ -104,7 +106,7 @@ public class AddOnDemandStaticImportAction extends PsiElementBaseIntentionAction
}
importList.add(importStaticStatement);
PsiFile[] roots = file.getPsiRoots();
List<PsiFile> roots = file.getViewProvider().getAllFiles();
for (final PsiFile root : roots) {
PsiElement copy = root.copy();
final PsiManager manager = root.getManager();
@@ -696,7 +696,7 @@ public class ImportHelper{
PsiFile context) {
String packageName = file.getPackageName();
final PsiElement[] roots = file.getPsiRoots();
final List<PsiFile> roots = file.getViewProvider().getAllFiles();
for (PsiElement root : roots) {
addNamesToImport(names, comments, root, packageName, context);
}
@@ -153,7 +153,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
}
else {
redundants = allImports;
final PsiElement[] roots = file.getPsiRoots();
final List<PsiFile> roots = file.getViewProvider().getAllFiles();
for (PsiElement root : roots) {
root.accept(new JavaRecursiveElementWalkingVisitor() {
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
@@ -23,10 +23,11 @@ import com.intellij.lang.Language;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
public class ClassFileViewProviderFactory implements FileViewProviderFactory{
@Override
public FileViewProvider createFileViewProvider(final VirtualFile file, final Language language, final PsiManager manager, final boolean physical) {
public FileViewProvider createFileViewProvider(@NotNull final VirtualFile file, final Language language, @NotNull final PsiManager manager, final boolean physical) {
// Define language for compiled file
final ContentBasedFileSubstitutor[] processors = Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME);
for (ContentBasedFileSubstitutor processor : processors) {
@@ -350,8 +350,13 @@ public class StubBuildingVisitor<T> implements ClassVisitor {
final String desc,
final String signature,
final String[] exceptions) {
if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null;
if ((access & Opcodes.ACC_BRIDGE) != 0) return null;
boolean isSynthetic = (access & Opcodes.ACC_SYNTHETIC) != 0;
// JLS 13.1 says: Any constructs introduced by the compiler that do not have a corresponding construct in the source code
// must be marked as synthetic, except for default constructors and the class initialization method.
// However Scala compiler erroneously generates ACC_BRIDGE instead of ACC_SYNTHETIC flag for in-trait implementation delegation. See IDEA-78649
if (isSynthetic) return null;
if (SYNTHETIC_CLINIT_METHOD.equals(name)) return null;
boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0;
@@ -108,7 +108,7 @@ public abstract class JavaParsingTestCase extends ParsingTestCase {
myFile = createPsiFile(name, text, parser);
myFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, myLanguageLevel);
try {
checkResult(name + ".txt", myFile);
checkResult(name, myFile);
}
catch (IOException e) {
throw new RuntimeException(e);
@@ -77,11 +77,13 @@ public class IncProjectBuilder {
}
catch (ProjectBuildException e) {
final Throwable cause = e.getCause();
if (cause instanceof PersistentEnumerator.CorruptedException || cause instanceof MappingFailedException) {
if (cause instanceof PersistentEnumerator.CorruptedException || cause instanceof MappingFailedException || cause instanceof IOException) {
// force rebuild
myMessageDispatcher.processMessage(new CompilerMessage(COMPILE_SERVER_NAME, BuildMessage.Kind.INFO,
"Internal caches are corrupted or have outdated format, forcing project rebuild: " +
e.getMessage()));
myMessageDispatcher.processMessage(new CompilerMessage(
COMPILE_SERVER_NAME, BuildMessage.Kind.INFO,
"Internal caches are corrupted or have outdated format, forcing project rebuild: " +
e.getMessage())
);
flushContext(context);
context = createContext(new AllProjectScope(scope.getProject(), Collections.<Artifact>emptySet(), true), false, true);
runBuild(context);
@@ -21,22 +21,27 @@ import org.jetbrains.annotations.NotNull;
import java.util.EventObject;
public abstract class DocumentEvent extends EventObject {
protected DocumentEvent(Document document) {
protected DocumentEvent(@NotNull Document document) {
super(document);
}
@NotNull public abstract Document getDocument();
@NotNull
public abstract Document getDocument();
public abstract int getOffset();
public abstract int getOldLength();
public abstract int getNewLength();
@NotNull
public abstract CharSequence getOldFragment();
@NotNull
public abstract CharSequence getNewFragment();
public abstract long getOldTimeStamp();
public boolean isWholeTextReplaced() {
return getOffset() == 0 && getNewLength() == getDocument().getTextLength();
}
@@ -18,6 +18,7 @@ package com.intellij.psi;
import com.intellij.lang.Language;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/**
* Register in extension point {@code com.intellij.fileType.fileViewProviderFactory}
@@ -26,5 +27,5 @@ import com.intellij.openapi.vfs.VirtualFile;
* @author yole
*/
public interface FileViewProviderFactory {
FileViewProvider createFileViewProvider(final VirtualFile file, final Language language, final PsiManager manager, final boolean physical);
FileViewProvider createFileViewProvider(@NotNull VirtualFile file, Language language, @NotNull PsiManager manager, final boolean physical);
}
@@ -66,7 +66,8 @@ public class LocalSearchScope extends SearchScope {
for (final PsiElement element : scope) {
LOG.assertTrue(element.getContainingFile() != null, element.getClass().getName());
if (element instanceof PsiFile) {
ContainerUtil.addAll(localScope, ((PsiFile)element).getPsiRoots());
List<PsiFile> files = ((PsiFile)element).getViewProvider().getAllFiles();
ContainerUtil.addAll(localScope, files);
}
else {
localScope.add(element);
@@ -713,7 +713,7 @@ public class PsiTreeUtil {
int offset,
@NotNull Class<T> clazz,
boolean strictStart) {
final PsiElement[] psiRoots = file.getPsiRoots();
final List<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
T result = null;
for (PsiElement root : psiRoots) {
final PsiElement elementAt = root.findElementAt(offset);
@@ -739,7 +739,7 @@ public class PsiTreeUtil {
@NotNull Class<T> clazz,
boolean strictStart,
@NotNull Class<? extends PsiElement>... stopAt) {
final PsiElement[] psiRoots = file.getPsiRoots();
final List<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
T result = null;
for (PsiElement root : psiRoots) {
final PsiElement elementAt = root.findElementAt(offset);
@@ -25,8 +25,8 @@ import com.intellij.util.diff.FilesTooBigForDiffException;
* is replaced.
* <p/>
* Example: consider that the user selects all text at editor (Ctrl+A), copies it to the buffer (Ctrl+C) and performs paste (Ctrl+V).
* All document text is replaced then but in essence it's the same, hence, we may want particular range markers to be still valid.
*
* All document text is replaced then but in essence it's the same, hence, we may want particular range markers to be still valid.
*
* @author max
*/
class PersistentRangeMarker extends RangeMarkerImpl {
@@ -69,22 +69,23 @@ class PersistentRangeMarker extends RangeMarkerImpl {
private boolean translateViaDiff(final DocumentEventImpl event) {
try {
myStartLine = event.translateLineViaDiffStrict(myStartLine);
if (myStartLine < 0 || myStartLine >= getDocument().getLineCount()){
if (myStartLine < 0 || myStartLine >= getDocument().getLineCount()) {
invalidate(event);
}
else{
else {
setIntervalStart(getDocument().getLineStartOffset(myStartLine) + myStartColumn);
}
myEndLine = event.translateLineViaDiffStrict(myEndLine);
if (myEndLine < 0 || myEndLine >= getDocument().getLineCount()){
if (myEndLine < 0 || myEndLine >= getDocument().getLineCount()) {
invalidate(event);
}
else{
else {
setIntervalEnd(getDocument().getLineStartOffset(myEndLine) + myEndColumn);
}
return true;
} catch (FilesTooBigForDiffException e) {
}
catch (FilesTooBigForDiffException e) {
return false;
}
}
@@ -94,12 +95,12 @@ class PersistentRangeMarker extends RangeMarkerImpl {
DocumentEventImpl event = (DocumentEventImpl)e;
final boolean shouldTranslateViaDiff = PersistentRangeMarkerUtil.shouldTranslateViaDiff(event, this);
boolean wasTranslated = shouldTranslateViaDiff;
if (shouldTranslateViaDiff){
if (shouldTranslateViaDiff) {
wasTranslated = translateViaDiff(event);
}
if (! wasTranslated) {
if (!wasTranslated) {
super.changedUpdateImpl(e);
if (isValid()){
if (isValid()) {
storeLinesAndCols(e);
}
}
@@ -38,6 +38,8 @@ public class DocumentEventImpl extends DocumentEvent {
private final long myOldTimeStamp;
private final boolean myIsWholeDocReplaced;
private Diff.Change myChange;
private static final Diff.Change TOO_BIG_FILE = new Diff.Change(0, 0, 0, 0, null) {
};
private int myOptimizedLineShift = -1;
private boolean myOptimizedLineShiftCalculated;
@@ -45,7 +47,11 @@ public class DocumentEventImpl extends DocumentEvent {
private int myOptimizedOldLineShift = -1;
private boolean myOptimizedOldLineShiftCalculated;
public DocumentEventImpl(Document document, int offset, CharSequence oldString, CharSequence newString, long oldTimeStamp,
public DocumentEventImpl(@NotNull Document document,
int offset,
CharSequence oldString,
CharSequence newString,
long oldTimeStamp,
boolean wholeTextReplaced) {
super(document);
myOffset = offset;
@@ -83,11 +89,13 @@ public class DocumentEventImpl extends DocumentEvent {
return myNewLength;
}
@NotNull
@Override
public CharSequence getOldFragment() {
return myOldString;
}
@NotNull
@Override
public CharSequence getNewFragment() {
return myNewString;
@@ -96,11 +104,11 @@ public class DocumentEventImpl extends DocumentEvent {
@Override
@NotNull
public Document getDocument() {
return (Document) getSource();
return (Document)getSource();
}
public int getStartOldIndex() {
if(isStartOldIndexCalculated) return myStartOldIndex;
if (isStartOldIndexCalculated) return myStartOldIndex;
isStartOldIndexCalculated = true;
myStartOldIndex = getDocument().getLineNumber(myOffset);
@@ -108,21 +116,21 @@ public class DocumentEventImpl extends DocumentEvent {
}
public boolean isOnlyOneLineChanged() {
if(isOnlyOneLineChangedCalculated) return isOnlyOneLineChanged;
if (isOnlyOneLineChangedCalculated) return isOnlyOneLineChanged;
isOnlyOneLineChangedCalculated = true;
isOnlyOneLineChanged = true;
for(int i=0; i<myOldString.length(); i++) {
if(myOldString.charAt(i) == '\n') {
for (int i = 0; i < myOldString.length(); i++) {
if (myOldString.charAt(i) == '\n') {
isOnlyOneLineChanged = false;
break;
}
}
if(isOnlyOneLineChanged) {
for(int i=0; i<myNewString.length(); i++) {
if(myNewString.charAt(i) == '\n') {
if (isOnlyOneLineChanged) {
for (int i = 0; i < myNewString.length(); i++) {
if (myNewString.charAt(i) == '\n') {
isOnlyOneLineChanged = false;
break;
}
@@ -148,10 +156,8 @@ public class DocumentEventImpl extends DocumentEvent {
}
public int translateLineViaDiff(int line) throws FilesTooBigForDiffException {
if (myChange == null) buildDiff();
if (myChange == null) return line;
Diff.Change change = myChange;
Diff.Change change = reBuildDiffIfNeeded();
if (change == null) return line;
int newLine = line;
@@ -159,7 +165,8 @@ public class DocumentEventImpl extends DocumentEvent {
if (line < change.line0) break;
if (line >= change.line0 + change.deleted) {
newLine += change.inserted - change.deleted;
} else {
}
else {
int delta = Math.min(change.inserted, line - change.line0);
newLine = change.line1 + delta;
break;
@@ -172,16 +179,23 @@ public class DocumentEventImpl extends DocumentEvent {
}
public int translateLineViaDiffStrict(int line) throws FilesTooBigForDiffException {
if (myChange == null) buildDiff();
Diff.Change change = myChange;
Diff.Change change = reBuildDiffIfNeeded();
if (change == null) return line;
return Diff.translateLine(change, line);
}
private void buildDiff() throws FilesTooBigForDiffException {
//Diff diff = new Diff(strings1, strings2);
//myChange = diff.diff_2(false);
myChange = Diff.buildChanges(myOldString, myNewString);
private Diff.Change reBuildDiffIfNeeded() throws FilesTooBigForDiffException {
if (myChange == TOO_BIG_FILE) throw new FilesTooBigForDiffException(0);
if (myChange == null) {
try {
myChange = Diff.buildChanges(myOldString, myNewString);
}
catch (FilesTooBigForDiffException e) {
myChange = TOO_BIG_FILE;
throw e;
}
}
return myChange;
}
public int getOptimizedLineShift() {
@@ -519,18 +519,17 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
}
roots[i++] = psi;
}
// getPsiRoots() returns languages in the same order
//if (roots.length > 1) {
// Arrays.sort(roots, FILE_BY_LANGUAGE_ID);
//}
if (roots.length > 1) {
Arrays.sort(roots, FILE_BY_LANGUAGE_ID);
}
return roots;
}
//private static final Comparator<PsiFile> FILE_BY_LANGUAGE_ID = new Comparator<PsiFile>() {
// @Override
// public int compare(PsiFile o1, PsiFile o2) {
// return o1.getLanguage().getID().compareTo(o2.getLanguage().getID());
// }
//};
private static final Comparator<PsiFile> FILE_BY_LANGUAGE_ID = new Comparator<PsiFile>() {
@Override
public int compare(PsiFile o1, PsiFile o2) {
return o1.getLanguage().getID().compareTo(o2.getLanguage().getID());
}
};
@Override
public boolean isPhysical() {
@@ -28,7 +28,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -91,7 +90,7 @@ public class ProblemsHolder {
private boolean isInPsiFile(@NotNull PsiElement element) {
PsiFile file = element.getContainingFile();
return ArrayUtil.indexOf(myFile.getPsiRoots(), file) != -1;
return myFile.getViewProvider() == file.getViewProvider();
}
private void redirectProblem(@NotNull final ProblemDescriptor problem, @NotNull final PsiElement target) {
@@ -42,6 +42,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
public class PsiUtilBase extends PsiUtilCore {
@@ -51,6 +52,12 @@ public class PsiUtilBase extends PsiUtilCore {
throw new IllegalAccessError();
}
};
public static final Comparator<Language> LANGUAGE_COMPARATOR = new Comparator<Language>() {
@Override
public int compare(Language o1, Language o2) {
return o1.getID().compareTo(o2.getID());
}
};
public static int getRootIndex(PsiElement root) {
ASTNode node = root.getNode();
@@ -59,11 +66,18 @@ public class PsiUtilBase extends PsiUtilCore {
}
if(node != null) root = node.getPsi();
final PsiFile containingFile = root.getContainingFile();
final PsiFile[] psiRoots = containingFile.getPsiRoots();
for (int i = 0; i < psiRoots.length; i++) {
if(root == psiRoots[i]) return i;
FileViewProvider provider = containingFile.getViewProvider();
Set<Language> languages = provider.getLanguages();
if (languages.size() == 1) {
return 0;
}
throw new RuntimeException("invalid element");
List<Language> array = new ArrayList<Language>(languages);
Collections.sort(array, LANGUAGE_COMPARATOR);
for (int i = 0; i < array.size(); i++) {
Language language = array.get(i);
if (provider.getPsi(language) == containingFile) return i;
}
throw new RuntimeException("Cannot find root for: "+root);
}
@NotNull
@@ -615,10 +615,8 @@ public abstract class CodeStyleAbstractPanel implements Disposable {
return myCurrentSettings;
}
public void setupCopyFromMenu(Menu copyMenu) {
if (copyMenu.getItemCount() > 0) {
copyMenu.removeAll();
}
public void setupCopyFromMenu(JPopupMenu copyMenu) {
copyMenu.removeAll();
}
public boolean isCopyFromMenuAvailable() {
@@ -28,7 +28,6 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.codeStyle.*;
import com.intellij.ui.components.JBTabbedPane;
import org.jetbrains.annotations.NotNull;
@@ -36,7 +35,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -47,15 +47,12 @@ import java.util.List;
*/
public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPanel {
private final static Icon COPY_ICON = IconLoader.getIcon("/actions/import.png");
private CodeStyleAbstractPanel myActiveTab;
private List<CodeStyleAbstractPanel> myTabs;
private JPanel myPanel;
private JTabbedPane myTabbedPane;
private PredefinedCodeStyle[] myPredefinedCodeStyles;
private PopupMenu myCopyFromMenu;
private JPopupMenu myCopyFromMenu;
protected TabbedLanguageCodeStylePanel(@Nullable Language language, CodeStyleSettings currentSettings, CodeStyleSettings settings) {
super(language, currentSettings, settings);
@@ -120,37 +117,22 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
myTabs = new ArrayList<CodeStyleAbstractPanel>();
myPanel.add(myTabbedPane);
initTabs(getSettings());
addSetFrom();
}
assert !myTabs.isEmpty();
}
private void addSetFrom() {
myPredefinedCodeStyles = getPredefinedStyles();
JLabel dummyLabel = new JLabel("");
myTabbedPane.addTab("Set From...", dummyLabel);
int dummyIndex = myTabbedPane.indexOfComponent(dummyLabel);
myTabbedPane.setEnabledAt(dummyIndex, false);
JPanel setFromPanel = new JPanel();
setFromPanel.setBorder(BorderFactory.createEtchedBorder());
setFromPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0));
final JLabel setFromLabel = new JLabel("Set from...");
setFromPanel.add(setFromLabel);
setFromLabel.setIcon(COPY_ICON);
setFromLabel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
initCopyFromMenu(setFromLabel);
myCopyFromMenu.show(e.getComponent(), e.getX(), e.getY());
}
});
myTabbedPane.setTabComponentAt(dummyIndex, setFromPanel);
public void showSetFrom(Object e) {
final Container component = (Container)e;
final Component[] components = component.getComponents();
final Component last = components[components.length - 1];
initCopyFromMenu(last);
myCopyFromMenu.show(last, 0, last.getHeight() + 3);
}
private void initCopyFromMenu(JComponent parent) {
private void initCopyFromMenu(Component component) {
if (myCopyFromMenu == null) {
myCopyFromMenu = new PopupMenu();
parent.add(myCopyFromMenu);
myCopyFromMenu = new JPopupMenu();
//component.add(myCopyFromMenu);
setupCopyFromMenu(myCopyFromMenu);
}
}
@@ -283,13 +265,13 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
@Override
public void setupCopyFromMenu(Menu copyMenu) {
public void setupCopyFromMenu(JPopupMenu copyMenu) {
super.setupCopyFromMenu(copyMenu);
if (myPredefinedCodeStyles.length > 0) {
Menu langs = new Menu("Language"); //TODO<rv>: Move to resource bundle
JMenuItem langs = new JMenuItem("Language"); //TODO<rv>: Move to resource bundle
copyMenu.add(langs);
fillLanguages(langs);
Menu predefined = new Menu("Predefined Style"); //TODO<rv>: Move to resource bundle
JMenuItem predefined = new JMenuItem("Predefined Style"); //TODO<rv>: Move to resource bundle
copyMenu.add(predefined);
fillPredefined(predefined);
}
@@ -299,14 +281,14 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
}
private void fillLanguages(Menu parentMenu) {
private void fillLanguages(JComponent parentMenu) {
Language[] languages = LanguageCodeStyleSettingsProvider.getLanguagesWithCodeStyleSettings();
@SuppressWarnings("UnnecessaryFullyQualifiedName")
java.util.List<MenuItem> langItems = new ArrayList<MenuItem>();
java.util.List<JMenuItem> langItems = new ArrayList<JMenuItem>();
for (final Language lang : languages) {
if (!lang.equals(getDefaultLanguage())) {
final String langName = LanguageCodeStyleSettingsProvider.getLanguageName(lang);
MenuItem langItem = new MenuItem(langName);
JMenuItem langItem = new JMenuItem(langName);
langItem.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
@@ -316,20 +298,20 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane
langItems.add(langItem);
}
}
Collections.sort(langItems, new Comparator<MenuItem>() {
Collections.sort(langItems, new Comparator<JMenuItem>() {
@Override
public int compare(MenuItem item1, MenuItem item2) {
return item1.getLabel().compareToIgnoreCase(item2.getLabel());
public int compare(JMenuItem item1, JMenuItem item2) {
return item1.getText().compareToIgnoreCase(item2.getText());
}
});
for (MenuItem langItem : langItems) {
for (JMenuItem langItem : langItems) {
parentMenu.add(langItem);
}
}
private void fillPredefined(Menu parentMenu) {
private void fillPredefined(JMenuItem parentMenu) {
for (final PredefinedCodeStyle predefinedCodeStyle : myPredefinedCodeStyles) {
MenuItem predefinedItem = new MenuItem(predefinedCodeStyle.getName());
JMenuItem predefinedItem = new JMenuItem(predefinedCodeStyle.getName());
parentMenu.add(predefinedItem);
predefinedItem.addActionListener(new ActionListener() {
@Override
@@ -16,18 +16,20 @@
package com.intellij.application.options.codeStyle;
import com.intellij.application.options.CodeStyleAbstractPanel;
import com.intellij.application.options.TabbedLanguageCodeStylePanel;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.codeStyle.CodeStyleSchemes;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -93,6 +95,7 @@ public class CodeStyleMainPanel extends JPanel implements LanguageSelectorListen
myDetailsComponent.setPaintBorder(false);
myDetailsComponent.setContent(mySettingsPanel);
myDetailsComponent.setText(getDisplayName());
myDetailsComponent.setBannerMinHeight(24);
add(myDetailsComponent.getComponent(), BorderLayout.CENTER);
@@ -120,6 +123,7 @@ public class CodeStyleMainPanel extends JPanel implements LanguageSelectorListen
ensureCurrentPanel().onSomethingChanged();
String schemeName = myModel.getSelectedScheme().getName();
myDetailsComponent.setText(schemeName);
updateSetFrom();
myLayout.show(mySettingsPanel, schemeName);
}
}
@@ -137,6 +141,21 @@ public class CodeStyleMainPanel extends JPanel implements LanguageSelectorListen
}
}
private void updateSetFrom() {
final CodeStyleAbstractPanel selectedPanel = ensureCurrentPanel().getSelectedPanel();
if (selectedPanel instanceof TabbedLanguageCodeStylePanel) {
myDetailsComponent.setBannerActions(new Action[]{new AbstractAction("Set from...") {
@Override
public void actionPerformed(ActionEvent e) {
final CodeStyleAbstractPanel selectedPanel = ensureCurrentPanel().getSelectedPanel();
if (selectedPanel instanceof TabbedLanguageCodeStylePanel) {
((TabbedLanguageCodeStylePanel)selectedPanel).showSetFrom(e.getSource());
}
}
}});
}
}
public NewCodeStyleSettingsPanel[] getPanels() {
final Collection<NewCodeStyleSettingsPanel> panels = mySettingsPanels.values();
return panels.toArray(new NewCodeStyleSettingsPanel[panels.size()]);
@@ -39,11 +39,13 @@ import com.intellij.profile.codeInspection.ui.ErrorsConfigurable;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.ui.Gray;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -55,6 +57,7 @@ import javax.swing.plaf.basic.BasicSliderUI;
import java.awt.*;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.List;
/**
* User: anna
@@ -70,7 +73,7 @@ public class HectorComponent extends JPanel {
private final String myTitle = EditorBundle.message("hector.highlighting.level.title");
public HectorComponent(PsiFile file) {
public HectorComponent(@NotNull PsiFile file) {
super(new GridBagLayout());
setBorder(BorderFactory.createEmptyBorder(0, 0, 7, 0));
myFile = file;
@@ -83,15 +86,8 @@ public class HectorComponent extends JPanel {
final boolean notInLibrary =
!fileIndex.isInLibrarySource(virtualFile) && !fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInContent(virtualFile);
final FileViewProvider viewProvider = myFile.getViewProvider();
//List<Language> languages = new ArrayList<Language>(viewProvider.getLanguages());
//Collections.sort(languages, new Comparator<Language>() {
// @Override
// public int compare(Language o1, Language o2) {
// return o1.getID().compareTo(o2.getID());
// }
//});
Collection<Language> languages = viewProvider.getLanguages();
List<Language> languages = new ArrayList<Language>(viewProvider.getLanguages());
Collections.sort(languages, PsiUtilBase.LANGUAGE_COMPARATOR);
for (Language language : languages) {
@SuppressWarnings("UseOfObsoleteCollectionType")
final Hashtable<Integer, JLabel> sliderLabels = new Hashtable<Integer, JLabel>();
@@ -20,6 +20,7 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightLevelUtil;
import com.intellij.lang.Language;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
@@ -36,6 +37,7 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiFile;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.ArrayUtil;
@@ -50,6 +52,7 @@ import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
private static final Icon IN_PROGRESS_ICON = IconLoader.getIcon("/general/errorsInProgress.png");
@@ -166,13 +169,15 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
List<String> noInspectionRoots = new ArrayList<String>();
List<String> noHighlightingRoots = new ArrayList<String>();
final PsiFile[] roots = myFile.getPsiRoots();
for (PsiFile file : roots) {
if (!HighlightLevelUtil.shouldHighlight(file)) {
noHighlightingRoots.add(file.getLanguage().getID());
FileViewProvider provider = myFile.getViewProvider();
Set<Language> languages = provider.getLanguages();
for (Language language : languages) {
PsiFile root = provider.getPsi(language);
if (!HighlightLevelUtil.shouldHighlight(root)) {
noHighlightingRoots.add(language.getID());
}
else if (!HighlightLevelUtil.shouldInspect(file)) {
noInspectionRoots.add(file.getLanguage().getID());
else if (!HighlightLevelUtil.shouldInspect(root)) {
noInspectionRoots.add(language.getID());
}
}
DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus();
@@ -180,7 +185,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
status.noHighlightingRoots = noHighlightingRoots.isEmpty() ? null : ArrayUtil.toStringArray(noHighlightingRoots);
status.errorCount = errorCount.clone();
status.rootsNumber = roots.length;
status.rootsNumber = languages.size();
fillDaemonCodeAnalyzerErrorsStatus(status, fillErrorsCount, severityRegistrar);
List<TextEditorHighlightingPass> passes = myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument);
status.passStati = passes.isEmpty() ? Collections.<ProgressableTextEditorHighlightingPass>emptyList() :
@@ -78,8 +78,8 @@ public class LossyEncodingInspection extends LocalInspectionTool {
@Nullable
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) return null;
if (ArrayUtil.find(file.getPsiRoots(), file) != 0) return null;
if (!file.isPhysical()) return null;
if (file.getViewProvider().getBaseLanguage() != file.getLanguage()) return null;
VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return null;
if (virtualFile.getFileSystem() != LocalFileSystem.getInstance()
@@ -811,9 +811,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private void updateTabsUI(final boolean validateNow) {
boolean hasToolbarContent = rebuildToolbar();
Set<String> usedNames = new HashSet<String>();
List<TabInfo> tabs = myTabs.getTabs();
for (TabInfo each : tabs) {
hasToolbarContent |= updateTabUI(each);
hasToolbarContent |= updateTabUI(each, usedNames);
}
int tabsCount = tabs.size();
for (RunnerContentUi child : myChildren) {
@@ -827,7 +828,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
private boolean updateTabUI(TabInfo tab) {
private boolean updateTabUI(TabInfo tab, Set<String> usedNames) {
TabImpl t = getTabFor(tab);
if (t == null) {
return false;
@@ -842,7 +843,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
String title = contents.size() > 1 ? t.getDisplayName() : null;
if (title == null) {
final String name = myLayoutSettings.getDefaultDisplayName(t.getDefaultIndex());
if (name != null && contents.size() > 1) {
if (name != null && contents.size() > 1 && !usedNames.contains(name)) {
title = name;
} else {
title = StringUtil.join(contents, new NotNullFunction<Content, String>() {
@@ -854,14 +855,16 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}, " | ");
}
}
usedNames.add(title);
tab.setHidden(true);
boolean hidden = true;
for (Content content : contents) {
if (!grid.isMinimized(content)) {
tab.setHidden(false);
hidden = false;
break;
}
}
tab.setHidden(hidden);
if (icon == null && contents.size() == 1) {
icon = contents.get(0).getIcon();
}
@@ -24,6 +24,11 @@ public class IndentInfo {
private final int mySpaces;
private final int myIndentSpaces;
private final int myLineFeeds;
//
// The flag is used for compatibility with older versions of Intellij IDEA where spaces could be replaced with tabs inside a line of code,
// not only in the beginning of the line.
//
private static boolean myInlineTabsEnabled = "true".equalsIgnoreCase(System.getProperty("enable.inline.tabs"));
/** @see WhiteSpace#setForceSkipTabulationsUsage(boolean) */
private boolean myForceSkipTabulationsUsage;
@@ -58,40 +63,47 @@ public class IndentInfo {
if (options.USE_TAB_CHARACTER && !myForceSkipTabulationsUsage) {
if (options.SMART_TABS) {
int tabCount = myIndentSpaces / options.TAB_SIZE;
int leftSpaces = myIndentSpaces - tabCount * options.TAB_SIZE;
if (tabCount > 0) {
StringUtil.repeatSymbol(buffer, '\t', tabCount);
}
if (leftSpaces + mySpaces > 0) {
StringUtil.repeatSymbol(buffer, ' ', leftSpaces + mySpaces);
}
return fillUsingSmartTabs(buffer, options);
}
else {
int size = getTotalSpaces();
while (size > 0) {
if (size >= options.TAB_SIZE) {
buffer.append('\t');
size -= options.TAB_SIZE;
}
else {
buffer.append(' ');
size--;
}
}
else if (myLineFeeds > 0 || myInlineTabsEnabled) {
return fillUsingTabs(buffer, options);
}
}
else {
int spaces = getTotalSpaces();
if (spaces > 0) {
StringUtil.repeatSymbol(buffer, ' ', spaces);
}
int spaces = getTotalSpaces();
if (spaces > 0) {
StringUtil.repeatSymbol(buffer, ' ', spaces);
}
return buffer.toString();
}
private String fillUsingTabs(StringBuffer buffer, CommonCodeStyleSettings.IndentOptions options) {
int size = getTotalSpaces();
while (size > 0) {
if (size >= options.TAB_SIZE) {
buffer.append('\t');
size -= options.TAB_SIZE;
}
else {
buffer.append(' ');
size--;
}
}
return buffer.toString();
}
private String fillUsingSmartTabs(StringBuffer buffer, CommonCodeStyleSettings.IndentOptions options) {
int tabCount = myIndentSpaces / options.TAB_SIZE;
int leftSpaces = myIndentSpaces - tabCount * options.TAB_SIZE;
if (tabCount > 0) {
StringUtil.repeatSymbol(buffer, '\t', tabCount);
}
if (leftSpaces + mySpaces > 0) {
StringUtil.repeatSymbol(buffer, ' ', leftSpaces + mySpaces);
}
return buffer.toString();
}
public int getTotalSpaces() {
return myIndentSpaces + mySpaces;
}
@@ -450,7 +450,7 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
}
}
void saveExpandedPaths() {
protected void saveExpandedPaths() {
if (myTree != null) {
TreeState treeState = TreeState.createOn(myTree);
myReadTreeState.put(getSubId(), treeState);
@@ -108,8 +108,7 @@ public class ScopeViewPane extends AbstractProjectViewPane {
myViewPanel = new ScopeTreeViewPanel(myProject);
Disposer.register(this, myViewPanel);
myViewPanel.initListeners();
updateFromRoot(true);
myViewPanel.selectScope(NamedScopesHolder.getScope(myProject, getSubId()));
myTree = myViewPanel.getTree();
PopupHandler.installPopupHandler(myTree, IdeActions.GROUP_SCOPE_VIEW_POPUP, ActionPlaces.SCOPE_VIEW_POPUP);
enableDnD();
@@ -152,7 +151,9 @@ public class ScopeViewPane extends AbstractProjectViewPane {
}
public ActionCallback updateFromRoot(boolean restoreExpandedPaths) {
saveExpandedPaths();
myViewPanel.selectScope(NamedScopesHolder.getScope(myProject, getSubId()));
restoreExpandedPaths();
return new ActionCallback.Done();
}
@@ -67,7 +67,11 @@ public class ViewerTreeStructure extends AbstractTreeStructure {
if (myRootPsiElement == null) {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
return myRootPsiElement instanceof PsiFile ? ((PsiFile)myRootPsiElement).getPsiRoots() : new Object[]{myRootPsiElement};
if (!(myRootPsiElement instanceof PsiFile)) {
return new Object[]{myRootPsiElement};
}
List<PsiFile> files = ((PsiFile)myRootPsiElement).getViewProvider().getAllFiles();
return PsiUtilCore.toPsiFileArray(files);
}
final Object[][] children = new Object[1][];
children[0] = ArrayUtil.EMPTY_OBJECT_ARRAY;
@@ -79,10 +83,8 @@ public class ViewerTreeStructure extends AbstractTreeStructure {
final ArrayList<Object> list = new ArrayList<Object>();
ASTNode root = element instanceof PsiElement? SourceTreeToPsiMap.psiElementToTree((PsiElement)element) :
element instanceof ASTNode? (ASTNode)element : null;
boolean injected = false;
if (element instanceof Inject) {
root = SourceTreeToPsiMap.psiElementToTree(((Inject)element).getPsi());
injected = true;
}
if (root != null) {
@@ -298,8 +298,8 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
public void run() {
try {
if (myManager.getProject().isDisposed()) throw new ProcessCanceledException();
PsiElement[] psiRoots = file.getPsiRoots();
Set<PsiElement> processed = new HashSet<PsiElement>(psiRoots.length * 2, (float)0.5);
List<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
Set<PsiElement> processed = new HashSet<PsiElement>(psiRoots.size() * 2, (float)0.5);
for (PsiElement psiRoot : psiRoots) {
if (progress != null) progress.checkCanceled();
if (!processed.add(psiRoot)) continue;
@@ -472,22 +472,23 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
while (range != null && !range.isEmpty()) {
if (range.getStartOffset() >= shredEndOffset) {
hostNum++;
shredEndOffset = shreds.get(hostNum).range.getEndOffset();
PsiLanguageInjectionHost.Shred shred = shreds.get(hostNum);
shredEndOffset = shred.range.getEndOffset();
prevHostEndOffset = range.getStartOffset();
host = shreds.get(hostNum).host;
host = shred.host;
escaper = escapers.get(hostNum);
rangeInsideHost = shreds.get(hostNum).getRangeInsideHost();
prefixLength = shreds.get(hostNum).prefix.length();
suffixLength = shreds.get(hostNum).suffix.length();
rangeInsideHost = shred.getRangeInsideHost();
prefixLength = shred.prefix.length();
suffixLength = shred.suffix.length();
}
//in prefix/suffix or spills over to next fragment
if (range.getStartOffset() < prevHostEndOffset + prefixLength) {
range = new TextRange(prevHostEndOffset + prefixLength, range.getEndOffset());
}
TextRange spilled = null;
if (range.getEndOffset() >= shredEndOffset - suffixLength) {
if (range.getEndOffset() > shredEndOffset - suffixLength) {
spilled = new TextRange(shredEndOffset, range.getEndOffset());
range = new TextRange(range.getStartOffset(), shredEndOffset);
range = new TextRange(range.getStartOffset(), shredEndOffset-suffixLength);
}
if (!range.isEmpty()) {
int start = escaper.getOffsetInHost(range.getStartOffset() - prevHostEndOffset - prefixLength, rangeInsideHost);
@@ -22,7 +22,7 @@ public class MockDocumentEvent extends DocumentEvent {
private final int myOffset;
private final long myTimestamp;
public MockDocumentEvent(Document document, int offset) {
public MockDocumentEvent(@NotNull Document document, int offset) {
super(document);
myOffset = offset;
myTimestamp = document.getModificationStamp();
@@ -45,10 +45,12 @@ public class MockDocumentEvent extends DocumentEvent {
return 0;
}
@NotNull
public CharSequence getOldFragment() {
return "";
}
@NotNull
public CharSequence getNewFragment() {
return "";
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -24,6 +24,7 @@ import com.intellij.ui.switcher.QuickActionProvider;
import com.intellij.util.ui.AwtVisitor;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -87,6 +88,7 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
repaint();
}
@Nullable
public Object getData(@NonNls String dataId) {
return QuickActionProvider.KEY.is(dataId) && myProvideQuickActions ? this : null;
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
@@ -101,7 +102,25 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
if (e.getClickCount() != 2) return;
if (pluginTable.columnAtPoint(e.getPoint()) < 0) return;
if (pluginTable.rowAtPoint(e.getPoint()) < 0) return;
new ActionInstallPlugin(AvailablePluginsManagerMain.this, installed).install();
IdeaPluginDescriptor[] selection = pluginTable.getSelectedObjects();
if (selection != null) {
boolean enabled = true;
for (IdeaPluginDescriptor descr : selection) {
if (descr instanceof PluginNode) {
enabled &= !PluginManagerColumnInfo.isDownloaded((PluginNode)descr);
if (((PluginNode)descr).getStatus() == PluginNode.STATUS_INSTALLED) {
enabled &= InstalledPluginsTableModel.hasNewerVersion(descr.getPluginId());
}
}
else if (descr instanceof IdeaPluginDescriptorImpl) {
PluginId id = descr.getPluginId();
enabled &= InstalledPluginsTableModel.hasNewerVersion(id);
}
}
if (enabled) {
new ActionInstallPlugin(AvailablePluginsManagerMain.this, installed).install();
}
}
}
});
}
@@ -6090,6 +6090,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
Rectangle visibleArea = getScrollingModel().getVisibleArea();
startToUse = yPositionToLogicalLine(visibleArea.getLocation().y);
endToUse = Math.min(endToUse, yPositionToLogicalLine(visibleArea.y + visibleArea.height));
if (endToUse <= startToUse) {
// There is a possible case that there is the only soft-wrapped line, i.e. end == start. We still want to update the
// size container's width then.
endToUse = Math.min(myLineWidths.size(), startToUse + 1);
}
}
int maxWidth = 0;
for (int i = startToUse; i < endToUse; i++) {
@@ -51,17 +51,14 @@ import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusFactory;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.PicoInitializationException;
import org.picocontainer.PicoIntrospectionException;
import org.picocontainer.*;
import org.picocontainer.defaults.AbstractComponentAdapter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Set;
public abstract class ParsingTestCase extends PlatformLiteFixture {
protected String myFilePrefix = "";
@@ -201,7 +198,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText());
assertEquals("psi text mismatch", text, myFile.getText());
if (checkResult){
checkResult(name + ".txt", myFile);
checkResult(name, myFile);
}
else{
toParseTreeText(myFile, skipSpaces(), includeRanges());
@@ -218,7 +215,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
myFile = createPsiFile(name, text);
ensureParsed(myFile);
assertEquals(text, myFile.getText());
checkResult(name + suffix + ".txt", myFile);
checkResult(name + suffix, myFile);
}
protected void doCodeTest(String code) throws IOException {
@@ -226,7 +223,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
myFile = createPsiFile("a", code);
ensureParsed(myFile);
assertEquals(code, myFile.getText());
checkResult(myFilePrefix + name + ".txt", myFile);
checkResult(myFilePrefix + name, myFile);
}
protected PsiFile createPsiFile(String name, String text) {
@@ -253,15 +250,18 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
String targetDataName,
boolean skipSpaces,
boolean printRanges) throws IOException {
final PsiElement[] psiRoots = checkAllPsiRoots? file.getPsiRoots() : PsiElement.EMPTY_ARRAY;
if(psiRoots.length > 1){
for (int i = 0; i < psiRoots.length; i++) {
final PsiElement psiRoot = psiRoots[i];
doCheckResult(myFullDataPath, targetDataName + "." + i, toParseTreeText(psiRoot, skipSpaces, printRanges).trim());
}
FileViewProvider provider = file.getViewProvider();
Set<Language> languages = provider.getLanguages();
if (!checkAllPsiRoots || languages.size() == 1) {
doCheckResult(myFullDataPath, targetDataName + ".txt", toParseTreeText(file, skipSpaces, printRanges).trim());
return;
}
else{
doCheckResult(myFullDataPath, targetDataName, toParseTreeText(file, skipSpaces, printRanges).trim());
for (Language language : languages) {
PsiFile root = provider.getPsi(language);
String expectedName = targetDataName + "." + language.getID() + ".txt";
doCheckResult(myFullDataPath, expectedName, toParseTreeText(root, skipSpaces, printRanges).trim());
}
}
@@ -297,8 +297,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
}
private static String doLoadFile(String myFullDataPath, String name) throws IOException {
String fullName = myFullDataPath + File.separatorChar + name;
String text = FileUtil.loadFile(new File(fullName), CharsetToolkit.UTF8).trim();
String text = FileUtil.loadFile(new File(myFullDataPath, name), CharsetToolkit.UTF8).trim();
text = StringUtil.convertLineSeparators(text);
return text;
}
@@ -128,11 +128,11 @@ public class ContainerUtil {
return list.subList(from, list.size());
}
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Iterable<T> appendix) {
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Iterable<? extends T> appendix) {
addAll(collection, appendix.iterator());
}
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Iterator<T> iterator) {
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Iterator<? extends T> iterator) {
while (iterator.hasNext()) {
T o = iterator.next();
collection.add(o);
@@ -516,7 +516,7 @@ public class ContainerUtil {
return collect(FilteringIterator.create((Iterator<T>)iterator, instanceOf));
}
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Enumeration<T> enumeration) {
public static <T> void addAll(@NotNull Collection<T> collection, @NotNull Enumeration<? extends T> enumeration) {
while (enumeration.hasMoreElements()) {
T element = enumeration.nextElement();
collection.add(element);
@@ -77,7 +77,11 @@ public class PersistentStringEnumerator extends PersistentEnumeratorDelegate<Str
String s = myIdToStringCache.get(idx);
if (s != null) return s;
}
return super.valueOf(idx);
String s = super.valueOf(idx);
if (myIdToStringCache != null && s != null) {
myIdToStringCache.put(idx, s);
}
return s;
}
@Override
@@ -24,7 +24,9 @@ import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.ui.CaptionPanel;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.containers.HashMap;
import com.intellij.xdebugger.XDebugSession;
@@ -85,6 +87,8 @@ public class XFramesView extends XDebugViewBase {
myThreadComboBox.addItemListener(new MyItemListener());
final ActionToolbar toolbar = createToolbar();
Wrapper threadsPanel = new Wrapper();
CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_COLOR, 0, 0, 1, 0);
threadsPanel.setBorder(border);
threadsPanel.add(toolbar.getComponent(), BorderLayout.EAST);
threadsPanel.add(myThreadComboBox, BorderLayout.CENTER);
myMainPanel.add(threadsPanel, BorderLayout.NORTH);
@@ -21,9 +21,12 @@ import com.intellij.ide.dnd.DnDManager;
import com.intellij.ide.dnd.DnDNativeTarget;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.AnActionButtonRunnable;
import com.intellij.ui.CaptionPanel;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.xdebugger.XDebugSession;
@@ -92,6 +95,10 @@ public class XWatchesView extends XDebugViewBase implements DnDNativeTarget {
executeAction(XDebuggerActions.XREMOVE_WATCH);
}
});
CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_COLOR,
SystemInfo.isMac ? 1 : 0, 0,
SystemInfo.isMac ? 0 : 1, 0);
decorator.setToolbarBorder(border);
myDecoratedPanel = decorator.createPanel();
myDecoratedPanel.setBorder(null);
@@ -21,7 +21,7 @@
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="android" />
<orderEntry type="module" module-name="ui-designer" />
<orderEntry type="module" module-name="ui-designer-new" />
</component>
</module>
@@ -6,5 +6,5 @@
<depends>com.intellij.java-i18n</depends>
<depends>com.intellij.properties</depends>
<depends>org.jetbrains.android</depends>
<depends>com.intellij.uiDesigner</depends>
<depends>com.intellij.ui-designer-new</depends>
</idea-plugin>
+1
View File
@@ -61,6 +61,7 @@
<orderEntry type="library" name="xpp3-1.1.4-min" level="project" />
<orderEntry type="module" module-name="IntentionPowerPackPlugin" />
<orderEntry type="module" module-name="testng" />
<orderEntry type="module" module-name="android-rt" />
</component>
</module>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
</content>
<orderEntry type="module" module-name="util" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" exported="">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/../lib/sdklib.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$MODULE_DIR$/../lib/src/sdklib_src.zip!/src" />
</SOURCES>
</library>
</orderEntry>
</component>
</module>
@@ -16,13 +16,12 @@
package org.jetbrains.android.compiler.tools;
import com.android.sdklib.IAndroidTarget;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.android.compiler.AndroidCompileUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -47,22 +46,22 @@ public final class AndroidApt {
private AndroidApt() {
}
public static Map<CompilerMessageCategory, List<String>> compile(@NotNull IAndroidTarget target,
int platformToolsRevision,
@NotNull String manifestFileOsPath,
@NotNull String aPackage,
@NotNull String outDirOsPath,
@NotNull String[] resourceDirsOsPaths,
@NotNull String[] libPackages,
boolean isLibrary) throws IOException {
final Map<CompilerMessageCategory, List<String>> messages = new HashMap<CompilerMessageCategory, List<String>>();
messages.put(CompilerMessageCategory.ERROR, new ArrayList<String>());
messages.put(CompilerMessageCategory.INFORMATION, new ArrayList<String>());
public static Map<AndroidCompilerMessageKind, List<String>> compile(@NotNull IAndroidTarget target,
int platformToolsRevision,
@NotNull String manifestFileOsPath,
@NotNull String aPackage,
@NotNull String outDirOsPath,
@NotNull String[] resourceDirsOsPaths,
@NotNull String[] libPackages,
boolean isLibrary) throws IOException {
final Map<AndroidCompilerMessageKind, List<String>> messages = new HashMap<AndroidCompilerMessageKind, List<String>>();
messages.put(AndroidCompilerMessageKind.ERROR, new ArrayList<String>());
messages.put(AndroidCompilerMessageKind.INFORMATION, new ArrayList<String>());
final File outOsDir = new File(outDirOsPath);
if (!outOsDir.exists()) {
if (!outOsDir.mkdirs()) {
messages.get(CompilerMessageCategory.ERROR).add("Unable to create directory " + outDirOsPath);
messages.get(AndroidCompilerMessageKind.ERROR).add("Unable to create directory " + outDirOsPath);
}
}
@@ -71,55 +70,55 @@ public final class AndroidApt {
/* We actually need to delete the manifest.java as it may become empty and
in this case aapt doesn't generate an empty one, but instead doesn't
touch it */
final File manifestJavaFile = new File(packageFolderOsPath + File.separatorChar + AndroidUtils.MANIFEST_JAVA_FILE_NAME);
final File manifestJavaFile = new File(packageFolderOsPath + File.separatorChar + AndroidCommonUtils.MANIFEST_JAVA_FILE_NAME);
if (manifestJavaFile.exists()) {
if (!FileUtil.delete(manifestJavaFile)) {
messages.get(CompilerMessageCategory.ERROR).add("Unable to delete " + manifestJavaFile.getPath());
messages.get(AndroidCompilerMessageKind.ERROR).add("Unable to delete " + manifestJavaFile.getPath());
}
}
final File rJavaFile = new File(packageFolderOsPath + File.separatorChar + AndroidUtils.R_JAVA_FILENAME);
final File rJavaFile = new File(packageFolderOsPath + File.separatorChar + AndroidCommonUtils.R_JAVA_FILENAME);
if (rJavaFile.exists()) {
if (!FileUtil.delete(rJavaFile)) {
messages.get(CompilerMessageCategory.ERROR).add("Unable to delete " + rJavaFile.getPath());
messages.get(AndroidCompilerMessageKind.ERROR).add("Unable to delete " + rJavaFile.getPath());
}
}
final File[] libRJavaFiles = new File[libPackages.length];
for (int i = 0; i < libPackages.length; i++) {
final String libPackageFolderOsPath = FileUtil.toSystemDependentName(outDirOsPath + '/' + libPackages[i].replace('.', '/'));
libRJavaFiles[i] = new File(libPackageFolderOsPath + File.separatorChar + AndroidUtils.R_JAVA_FILENAME);
libRJavaFiles[i] = new File(libPackageFolderOsPath + File.separatorChar + AndroidCommonUtils.R_JAVA_FILENAME);
}
for (File libRJavaFile : libRJavaFiles) {
if (libRJavaFile.exists()) {
if (!FileUtil.delete(libRJavaFile)) {
messages.get(CompilerMessageCategory.ERROR).add("Unable to delete " + libRJavaFile.getPath());
messages.get(AndroidCompilerMessageKind.ERROR).add("Unable to delete " + libRJavaFile.getPath());
}
}
}
if (platformToolsRevision < 0 || platformToolsRevision > 7) {
Map<CompilerMessageCategory, List<String>> map =
Map<AndroidCompilerMessageKind, List<String>> map =
doCompile(target, manifestFileOsPath, outDirOsPath, resourceDirsOsPaths, libPackages, null, isLibrary);
if (map.get(CompilerMessageCategory.ERROR).isEmpty()) {
if (map.get(AndroidCompilerMessageKind.ERROR).isEmpty()) {
makeFieldsNotFinal(libRJavaFiles);
}
AndroidCompileUtil.addMessages(messages, map);
ExecutionUtil.addMessages(messages, map);
return messages;
}
else {
Map<CompilerMessageCategory, List<String>> map;
Map<AndroidCompilerMessageKind, List<String>> map;
map = doCompile(target, manifestFileOsPath, outDirOsPath, resourceDirsOsPaths, ArrayUtil.EMPTY_STRING_ARRAY, null, false);
AndroidCompileUtil.addMessages(messages, map);
ExecutionUtil.addMessages(messages, map);
for (String libPackage : libPackages) {
map = doCompile(target, manifestFileOsPath, outDirOsPath, resourceDirsOsPaths, ArrayUtil.EMPTY_STRING_ARRAY, libPackage, false);
AndroidCompileUtil.addMessages(messages, map);
ExecutionUtil.addMessages(messages, map);
}
return messages;
}
@@ -148,13 +147,13 @@ public final class AndroidApt {
}
}
private static Map<CompilerMessageCategory, List<String>> doCompile(@NotNull IAndroidTarget target,
@NotNull String manifestFileOsPath,
@NotNull String outDirOsPath,
@NotNull String[] resourceDirsOsPaths,
@NotNull String[] extraPackages,
@Nullable String customPackage,
boolean nonConstantIds)
private static Map<AndroidCompilerMessageKind, List<String>> doCompile(@NotNull IAndroidTarget target,
@NotNull String manifestFileOsPath,
@NotNull String outDirOsPath,
@NotNull String[] resourceDirsOsPaths,
@NotNull String[] extraPackages,
@Nullable String customPackage,
boolean nonConstantIds)
throws IOException {
final List<String> args = new ArrayList<String>();
@@ -174,7 +173,7 @@ public final class AndroidApt {
args.add("--extra-packages");
args.add(toPackagesString(extraPackages));
}
if (customPackage != null) {
args.add("--custom-package");
args.add(customPackage);
@@ -193,8 +192,8 @@ public final class AndroidApt {
args.add("-I");
args.add(target.getPath(IAndroidTarget.ANDROID_JAR));
LOG.info(AndroidUtils.command2string(args));
return ExecutionUtil.execute(ArrayUtil.toStringArray(args));
LOG.info(AndroidCommonUtils.command2string(args));
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(args));
}
@NotNull
@@ -209,9 +208,9 @@ public final class AndroidApt {
return builder.toString();
}
public static Map<CompilerMessageCategory, List<String>> crunch(@NotNull IAndroidTarget target,
@NotNull List<String> resPaths,
@NotNull String outputPath) throws IOException {
public static Map<AndroidCompilerMessageKind, List<String>> crunch(@NotNull IAndroidTarget target,
@NotNull List<String> resPaths,
@NotNull String outputPath) throws IOException {
final ArrayList<String> args = new ArrayList<String>();
//noinspection deprecation
@@ -227,19 +226,19 @@ public final class AndroidApt {
args.add("-C");
args.add(outputPath);
LOG.info(AndroidUtils.command2string(args));
return ExecutionUtil.execute(ArrayUtil.toStringArray(args));
LOG.info(AndroidCommonUtils.command2string(args));
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(args));
}
public static Map<CompilerMessageCategory, List<String>> packageResources(@NotNull IAndroidTarget target,
int platformToolsRevision,
@NotNull String manifestPath,
@NotNull String[] resPaths,
@Nullable String osAssetsPath,
@NotNull String outputPath,
@Nullable String configFilter,
boolean debugMode,
int versionCode) throws IOException {
public static Map<AndroidCompilerMessageKind, List<String>> packageResources(@NotNull IAndroidTarget target,
int platformToolsRevision,
@NotNull String manifestPath,
@NotNull String[] resPaths,
@Nullable String osAssetsPath,
@NotNull String outputPath,
@Nullable String configFilter,
boolean debugMode,
int versionCode) throws IOException {
final ArrayList<String> args = new ArrayList<String>();
//noinspection deprecation
@@ -290,7 +289,7 @@ public final class AndroidApt {
args.add("-F");
args.add(outputPath);
LOG.info(AndroidUtils.command2string(args));
return ExecutionUtil.execute(ArrayUtil.toStringArray(args));
LOG.info(AndroidCommonUtils.command2string(args));
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(args));
}
}
@@ -16,8 +16,8 @@
package org.jetbrains.android.compiler.tools;
import com.android.sdklib.IAndroidTarget;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.util.ArrayUtil;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,20 +36,22 @@ public final class AndroidIdl {
}
@NotNull
public static Map<CompilerMessageCategory, List<String>> execute(@NotNull IAndroidTarget target,
@NotNull String file,
@NotNull String outFile,
@NotNull String[] sourceRootPaths) throws IOException {
List<String> commands = new ArrayList<String>();
String frameworkAidlPath = target.getPath(IAndroidTarget.ANDROID_AIDL);
public static Map<AndroidCompilerMessageKind, List<String>> execute(@NotNull IAndroidTarget target,
@NotNull String file,
@NotNull String outFile,
@NotNull String[] sourceRootPaths) throws IOException {
final List<String> commands = new ArrayList<String>();
final String frameworkAidlPath = target.getPath(IAndroidTarget.ANDROID_AIDL);
commands.add(target.getPath(IAndroidTarget.AIDL));
commands.add("-p" + frameworkAidlPath);
for (String path : sourceRootPaths) {
commands.add("-I" + path);
}
commands.add(file);
commands.add(outFile);
return ExecutionUtil.execute(ArrayUtil.toStringArray(commands));
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(commands));
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.android.util;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidCommonUtils {
@NonNls public static final Object MANIFEST_JAVA_FILE_NAME = "Manifest.java";
public static final String R_JAVA_FILENAME = "R.java";
private AndroidCommonUtils() {
}
public static String command2string(@NotNull Collection<String> command) {
final StringBuilder builder = new StringBuilder();
for (Iterator<String> it = command.iterator(); it.hasNext(); ) {
String s = it.next();
builder.append('[');
builder.append(s);
builder.append(']');
if (it.hasNext()) {
builder.append(' ');
}
}
return builder.toString();
}
}
@@ -0,0 +1,8 @@
package org.jetbrains.android.util;
/**
* @author Eugene.Kudelevsky
*/
public enum AndroidCompilerMessageKind {
ERROR, INFORMATION, WARNING
}
@@ -0,0 +1,61 @@
package org.jetbrains.android.util;
import com.intellij.execution.process.BaseOSProcessHandler;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidOSProcessHandler extends BaseOSProcessHandler {
@NonNls private static final String IGNORING = "ignoring";
@NonNls private static final String SKIPPING = "skipping";
private final List<String> myInfoMessages = new ArrayList<String>();
private final List<String> myErrorMessages = new ArrayList<String>();
public AndroidOSProcessHandler(@NotNull final Process process, @Nullable final String commandLine) {
super(process, commandLine, null);
}
@Override
public void notifyTextAvailable(String text, Key outputType) {
super.notifyTextAvailable(text, outputType);
if (StringUtil.isEmptyOrSpaces(text)) {
return;
}
String[] lines = text.split("[\\n\\r]+");
for (String line : lines) {
String l = line.toLowerCase();
if (outputType == ProcessOutputTypes.STDOUT) {
myInfoMessages.add(line);
}
else if (outputType == ProcessOutputTypes.STDERR) {
if (l.contains(IGNORING) || l.contains(SKIPPING)) {
myInfoMessages.add(line);
}
else {
myErrorMessages.add(line);
}
}
}
}
@NotNull
public List<String> getInfoMessages() {
return myInfoMessages;
}
@NotNull
public List<String> getErrorMessages() {
return myErrorMessages;
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2000-2010 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.android.util;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Abstract external tool for compiler.
*
* @author Alexey Efimov
*/
public final class ExecutionUtil {
private ExecutionUtil() {
}
@NotNull
public static Map<AndroidCompilerMessageKind, List<String>> doExecute(String... argv) throws IOException {
ProcessBuilder builder = new ProcessBuilder(argv);
ProcessResult result = readProcessOutput(builder.start());
Map<AndroidCompilerMessageKind, List<String>> messages = result.getMessages();
int code = result.getExitCode();
List<String> errMessages = messages.get(AndroidCompilerMessageKind.ERROR);
if (code != 0 && errMessages.isEmpty()) {
throw new IOException("Command \"" + concat(argv) + "\" execution failed with exit code " + code);
}
else {
if (code == 0) {
messages.get(AndroidCompilerMessageKind.INFORMATION).addAll(errMessages);
errMessages.clear();
}
return messages;
}
}
private static String concat(String... strs) {
StringBuilder builder = new StringBuilder();
for (int i = 0, n = strs.length; i < n; i++) {
builder.append(strs[i]);
if (i < n - 1) {
builder.append(' ');
}
}
return builder.toString();
}
@NotNull
private static ProcessResult readProcessOutput(Process process) throws IOException {
final AndroidOSProcessHandler handler = new AndroidOSProcessHandler(process, "");
handler.startNotify();
handler.waitFor();
int exitCode = handler.getProcess().exitValue();
return new ProcessResult(handler.getInfoMessages(), handler.getErrorMessages(), exitCode);
}
private static final class ProcessResult {
private final int myExitCode;
private final Map<AndroidCompilerMessageKind, List<String>> myMessages;
public ProcessResult(List<String> information, List<String> error, int exitCode) {
myExitCode = exitCode;
myMessages = new HashMap<AndroidCompilerMessageKind, List<String>>(2);
myMessages.put(AndroidCompilerMessageKind.INFORMATION, information);
myMessages.put(AndroidCompilerMessageKind.ERROR, error);
}
public Map<AndroidCompilerMessageKind, List<String>> getMessages() {
return myMessages;
}
public int getExitCode() {
return myExitCode;
}
}
public static <T> void addMessages(@NotNull Map<T, List<String>> messages, @NotNull Map<T, List<String>> toAdd) {
for (Map.Entry<T, List<String>> entry : toAdd.entrySet()) {
List<String> list = messages.get(entry.getKey());
if (list == null) {
list = new ArrayList<String>();
messages.put(entry.getKey(), list);
}
list.addAll(entry.getValue());
}
}
}
@@ -19,15 +19,11 @@ import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.project.Project;
import org.jetbrains.android.compiler.AndroidPrecompileTask;
import org.jetbrains.annotations.NotNull;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidProjectComponent extends AbstractProjectComponent {
private volatile boolean myCompilationRunning = false;
private final Object COMPILATION_FLAG_LOCK = new Object();
protected AndroidProjectComponent(Project project) {
super(project);
}
@@ -35,26 +31,6 @@ public class AndroidProjectComponent extends AbstractProjectComponent {
@Override
public void projectOpened() {
final CompilerManager manager = CompilerManager.getInstance(myProject);
manager.addBeforeTask(new AndroidPrecompileTask(this));
}
public void setCompilationStarted() {
synchronized (COMPILATION_FLAG_LOCK) {
myCompilationRunning = true;
}
}
public void setCompilationFinished() {
synchronized (COMPILATION_FLAG_LOCK) {
myCompilationRunning = false;
}
}
public void runIfNotInCompilation(@NotNull Runnable r) {
synchronized (COMPILATION_FLAG_LOCK) {
if (!myCompilationRunning) {
r.run();
}
}
manager.addBeforeTask(new AndroidPrecompileTask());
}
}
@@ -26,6 +26,7 @@ import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import org.jetbrains.android.compiler.AndroidAptCompiler;
import org.jetbrains.android.compiler.AndroidAutogeneratorMode;
import org.jetbrains.android.compiler.AndroidCompileUtil;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.util.AndroidBundle;
@@ -96,7 +97,10 @@ public class AndroidRegenerateRJavaFileAction extends AnAction {
@Override
public boolean execute(CompileContext context) {
// todo: compatibility with background autogenerating
AndroidCompileUtil.generate(new AndroidAptCompiler(), context);
for (Module module : modules) {
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AAPT, context);
}
return true;
}
}, new ModuleCompileScope(project, modules, false), AndroidBundle.message("android.compile.messages.generating.r.java.content.name"),
@@ -17,19 +17,16 @@ package org.jetbrains.android.compiler;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.compiler.tools.AndroidApt;
import org.jetbrains.android.dom.manifest.Manifest;
@@ -39,13 +36,13 @@ import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.maven.AndroidMavenUtil;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.*;
@@ -58,6 +55,7 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidAptCompiler");
private static final GenerationItem[] EMPTY_GENERATION_ITEM_ARRAY = {};
@Nullable
@Override
public VirtualFile getPresentableFile(CompileContext context, Module module, VirtualFile outputRoot, VirtualFile generatedFile) {
return null;
@@ -77,37 +75,15 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
public GenerationItem[] generate(final CompileContext context, final GenerationItem[] items, VirtualFile outputRootDirectory) {
if (items != null && items.length > 0) {
context.getProgressIndicator().setText(AndroidBundle.message("android.compile.messages.generating.r.java"));
Computable<GenerationItem[]> computation = new Computable<GenerationItem[]>() {
public GenerationItem[] compute() {
if (context.getProject().isDisposed()) {
return EMPTY_GENERATION_ITEM_ARRAY;
}
return doGenerate(context, items);
}
};
GenerationItem[] generationItems = computation.compute();
List<VirtualFile> generatedVFiles = new ArrayList<VirtualFile>();
for (GenerationItem item : generationItems) {
final Set<File> generatedFiles = ((AptGenerationItem)item).myGeneratedFile2Package.keySet();
for (File generatedFile : generatedFiles) {
CompilerUtil.refreshIOFile(generatedFile);
CompilerUtil.refreshIOFile(generatedFile.getParentFile());
VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(generatedFile);
if (generatedVFile != null) {
generatedVFiles.add(generatedVFile);
}
}
if (!context.getProject().isDisposed()) {
return doGenerate(context, items, outputRootDirectory);
}
if (context instanceof CompileContextEx) {
((CompileContextEx)context).markGenerated(generatedVFiles);
}
return generationItems;
}
return EMPTY_GENERATION_ITEM_ARRAY;
}
private static GenerationItem[] doGenerate(final CompileContext context, GenerationItem[] items) {
private static GenerationItem[] doGenerate(final CompileContext context, GenerationItem[] items, VirtualFile outputRootDirectory) {
List<GenerationItem> results = new ArrayList<GenerationItem>(items.length);
for (GenerationItem item : items) {
if (item instanceof AptGenerationItem) {
@@ -117,33 +93,19 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
continue;
}
final String outputDirOsPath = FileUtil.toSystemDependentName(outputRootDirectory.getPath());
try {
Map<CompilerMessageCategory, List<String>> messages = AndroidApt.compile(aptItem.myAndroidTarget, aptItem.myPlatformToolsRevision,
aptItem.myManifestFile.getPath(), aptItem.myPackage,
aptItem.mySourceRootPath, aptItem.myResourcesPaths,
aptItem.myLibraryPackages, aptItem.myIsLibrary);
Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidApt.compile(aptItem.myAndroidTarget, aptItem.myPlatformToolsRevision,
aptItem.myManifestFile.getPath(), aptItem.myPackage,
outputDirOsPath, aptItem.myResourcesPaths,
aptItem.myLibraryPackages, aptItem.myIsLibrary));
AndroidCompileUtil.addMessages(context, messages);
if (messages.get(CompilerMessageCategory.ERROR).isEmpty()) {
results.add(aptItem);
}
for (Map.Entry<File, String> entry : aptItem.myGeneratedFile2Package.entrySet()) {
final File generatedFile = entry.getKey();
final String aPackage = entry.getValue();
if (generatedFile.exists()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (context.getProject().isDisposed() || aptItem.myModule.isDisposed()) {
return;
}
String className = FileUtil.getNameWithoutExtension(generatedFile);
AndroidCompileUtil.removeDuplicatingClasses(aptItem.myModule, aPackage, className,
generatedFile, aptItem.mySourceRootPath);
}
});
}
}
}
catch (final IOException e) {
LOG.info(e);
@@ -183,22 +145,17 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
final Module myModule;
final VirtualFile myManifestFile;
final String[] myResourcesPaths;
final String mySourceRootPath;
final IAndroidTarget myAndroidTarget;
final Map<File, String> myGeneratedFile2Package;
final String myPackage;
final String[] myLibraryPackages;
final boolean myIsLibrary;
private final Set<String> myNonExistingFiles;
final int myPlatformToolsRevision;
private AptGenerationItem(@NotNull Module module,
@NotNull VirtualFile manifestFile,
@NotNull String[] resourcesPaths,
@NotNull String sourceRootPath,
@NotNull IAndroidTarget target,
int platformToolsRevision,
@NotNull String aPackage,
@@ -207,55 +164,19 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
myModule = module;
myManifestFile = manifestFile;
myResourcesPaths = resourcesPaths;
mySourceRootPath = sourceRootPath;
myAndroidTarget = target;
myPackage = aPackage;
myLibraryPackages = libPackages;
myIsLibrary = isLibrary;
myPlatformToolsRevision = platformToolsRevision;
myGeneratedFile2Package = new HashMap<File, String>();
myGeneratedFile2Package.put(
new File(sourceRootPath, aPackage.replace('.', File.separatorChar) + File.separator + AndroidUtils.R_JAVA_FILENAME), aPackage);
for (String libPackage : myLibraryPackages) {
myGeneratedFile2Package
.put(new File(sourceRootPath, libPackage.replace('.', File.separatorChar) + File.separator + AndroidUtils.R_JAVA_FILENAME),
libPackage);
}
myNonExistingFiles = new HashSet<String>();
// We need to check only R.java files, not Manifest.java files, so add Manifest files LATER
for (File generatedFile : myGeneratedFile2Package.keySet()) {
if (!generatedFile.exists()) {
myNonExistingFiles.add(FileUtil.toSystemIndependentName(generatedFile.getPath()));
}
}
myGeneratedFile2Package.put(
new File(sourceRootPath, aPackage.replace('.', File.separatorChar) + File.separator + AndroidUtils.MANIFEST_JAVA_FILE_NAME),
aPackage);
for (String libraryPackage : myLibraryPackages) {
myGeneratedFile2Package.put(
new File(sourceRootPath, libraryPackage.replace('.', File.separatorChar) + File.separator + AndroidUtils.MANIFEST_JAVA_FILE_NAME),
libraryPackage);
}
}
@NotNull
public Map<File, String> getGeneratedFiles() {
return myGeneratedFile2Package;
}
public String getPath() {
return myPackage.replace('.', '/') + '/' + AndroidUtils.R_JAVA_FILENAME;
return myPackage.replace('.', '/') + '/' + AndroidCommonUtils.R_JAVA_FILENAME;
}
public ValidityState getValidityState() {
return new MyValidityState(myModule, myNonExistingFiles, myPlatformToolsRevision);
return new MyValidityState(myModule, Collections.<String>emptySet(), myPlatformToolsRevision);
}
public Module getModule() {
@@ -265,11 +186,6 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
public boolean isTestSource() {
return false;
}
@NotNull
public String getPackageFolderPath() {
return FileUtil.toSystemDependentName(mySourceRootPath + '/' + myPackage.replace('.', '/'));
}
}
@Nullable
@@ -338,13 +254,14 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
String sourceRootPath = facet.getAptGenSourceRootPath();
if (sourceRootPath == null) {
myContext.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.apt.gen.not.specified", module.getName()), null, -1, -1);
AndroidBundle.message("android.compilation.error.apt.gen.not.specified", module.getName()),
null, -1, -1);
continue;
}
final String[] libPackages = getLibPackages(module, packageName);
items.add(new AptGenerationItem(module, manifestFile, resPaths, sourceRootPath, target, platformToolsRevision,
items.add(new AptGenerationItem(module, manifestFile, resPaths, target, platformToolsRevision,
packageName, libPackages, facet.getConfiguration().LIBRARY_PROJECT));
}
}
@@ -364,7 +281,7 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler {
}
}
return result.toArray(new String[result.size()]);
return ArrayUtil.toStringArray(result);
}
}
@@ -0,0 +1,628 @@
package org.jetbrains.android.compiler;
import com.android.AndroidConstants;
import com.android.sdklib.IAndroidTarget;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.ModuleCompileScope;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.compiler.tools.AndroidApt;
import org.jetbrains.android.compiler.tools.AndroidIdl;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.fileTypes.AndroidIdlFileType;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidAutogenerator {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidAutogenerator");
private AndroidAutogenerator() {
}
public static void run(@NotNull AndroidAutogeneratorMode mode, @NotNull AndroidFacet facet, @NotNull CompileContext context) {
final Set<String> obsoleteFiles = new HashSet<String>(facet.getAutogeneratedFiles(mode));
switch (mode) {
case AAPT:
runAapt(facet, context);
break;
case AIDL:
runAidl(facet, context);
break;
case RENDERSCRIPT:
runRenderscript(facet, context);
break;
default:
LOG.error("Unknown mode" + mode);
}
obsoleteFiles.removeAll(facet.getAutogeneratedFiles(mode));
for (String path : obsoleteFiles) {
final File file = new File(path);
if (file.isFile()) {
FileUtil.delete(file);
CompilerUtil.refreshIOFile(file);
}
}
}
private static void runAapt(@NotNull final AndroidFacet facet, @NotNull final CompileContext context) {
final Module module = facet.getModule();
final AptAutogenerationItem item = ApplicationManager.getApplication().runReadAction(new Computable<AptAutogenerationItem>() {
@Nullable
@Override
public AptAutogenerationItem compute() {
if (module.isDisposed() || module.getProject().isDisposed()) {
return null;
}
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
if (platform == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.specify.platform", module.getName()), null, -1, -1);
return null;
}
final IAndroidTarget target = platform.getTarget();
final int platformToolsRevision = platform.getSdk().getPlatformToolsRevision();
final String[] resPaths = AndroidCompileUtil.collectResourceDirs(facet, false, context);
if (resPaths.length == 0) {
return null;
}
final VirtualFile manifestFile = AndroidRootUtil.getManifestFileForCompiler(facet);
if (manifestFile == null) {
context.addMessage(CompilerMessageCategory.ERROR, AndroidBundle.message("android.compilation.error.manifest.not.found"),
null, -1, -1);
return null;
}
final Manifest manifest = AndroidUtils.loadDomElement(module, manifestFile, Manifest.class);
if (manifest == null) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot parse file", manifestFile.getUrl(), -1, -1);
return null;
}
String packageName = manifest.getPackage().getValue();
if (packageName != null) {
packageName = packageName.trim();
}
if (packageName == null || packageName.length() <= 0) {
context.addMessage(CompilerMessageCategory.ERROR, AndroidBundle.message("package.not.found.error"), manifestFile.getUrl(),
-1, -1);
return null;
}
final String sourceRootPath = facet.getAptGenSourceRootPath();
if (sourceRootPath == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.apt.gen.not.specified", module.getName()),
null, -1, -1);
return null;
}
final Map<String, String> genFilePath2Package = new HashMap<String, String>();
final String packageDir = packageName.replace('.', '/') + '/';
genFilePath2Package.put(packageDir + AndroidCommonUtils.MANIFEST_JAVA_FILE_NAME, packageName);
genFilePath2Package.put(packageDir + AndroidCommonUtils.R_JAVA_FILENAME, packageName);
final String manifestFileOsPath = FileUtil.toSystemDependentName(manifestFile.getPath());
return new AptAutogenerationItem(target, platformToolsRevision, manifestFileOsPath, packageName, sourceRootPath, resPaths,
facet.getConfiguration().LIBRARY_PROJECT, genFilePath2Package);
}
});
if (item == null) {
return;
}
final Set<VirtualFile> filesToCheck = new HashSet<VirtualFile>();
for (String genFileRelPath : item.myGenFileRelPath2package.keySet()) {
final String genFileFullPath = item.myOutputDirOsPath + '/' + genFileRelPath;
if (new File(genFileFullPath).exists()) {
final VirtualFile genFile = LocalFileSystem.getInstance().findFileByPath(genFileFullPath);
if (genFile != null) {
filesToCheck.add(genFile);
}
}
}
if (!ensureFilesWritable(module.getProject(), filesToCheck)) {
return;
}
File tempOutDir = null;
try {
// Aapt generation can be very long, so we generate it in temp directory first
tempOutDir = FileUtil.createTempDirectory("android_apt_autogeneration", "tmp");
final Map<AndroidCompilerMessageKind, List<String>> messages =
AndroidApt.compile(item.myTarget, item.myPlatformToolsRevision, item.myManifestFileOsPath, item.myPackage,
tempOutDir.getPath(), item.myResDirOsPaths, ArrayUtil.EMPTY_STRING_ARRAY, item.myLibrary);
if (messages.get(AndroidCompilerMessageKind.ERROR).size() == 0) {
for (String genFileRelPath : item.myGenFileRelPath2package.keySet()) {
final File srcFile = new File(tempOutDir.getPath() + '/' + genFileRelPath);
if (srcFile.isFile()) {
final File dstFile = new File(item.myOutputDirOsPath + '/' + genFileRelPath);
if (dstFile.exists()) {
if (!FileUtil.delete(dstFile)) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
if (module.isDisposed() || module.getProject().isDisposed()) {
return;
}
context.addMessage(CompilerMessageCategory.ERROR,
"Cannot delete " + FileUtil.toSystemDependentName(dstFile.getPath()), null, -1, -1);
}
});
}
}
FileUtil.rename(srcFile, dstFile);
}
}
}
AndroidCompileUtil.addMessages(context, AndroidCompileUtil.toCompilerMessageCategoryKeys(messages));
for (Map.Entry<String, String> entry : item.myGenFileRelPath2package.entrySet()) {
final String path = item.myOutputDirOsPath + '/' + entry.getKey();
final String aPackage = entry.getValue();
final File file = new File(path);
CompilerUtil.refreshIOFile(file);
removeAllFilesWithSameName(module, file, item.myOutputDirOsPath);
removeDuplicateClasses(module, aPackage, file, item.myOutputDirOsPath);
}
final VirtualFile genSourceRoot = LocalFileSystem.getInstance().findFileByPath(item.myOutputDirOsPath);
if (genSourceRoot != null) {
genSourceRoot.refresh(false, true);
}
if (messages.get(AndroidCompilerMessageKind.ERROR).size() == 0) {
facet.clearAutogeneratedFiles(AndroidAutogeneratorMode.AAPT);
for (String relPath : item.myGenFileRelPath2package.keySet()) {
final VirtualFile genFile = LocalFileSystem.getInstance().findFileByPath(item.myOutputDirOsPath + '/' + relPath);
if (genFile != null && genFile.exists()) {
facet.markFileAutogenerated(AndroidAutogeneratorMode.AAPT, genFile);
}
}
}
}
catch (final IOException e) {
LOG.info(e);
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (module.getProject().isDisposed()) return;
context.addMessage(CompilerMessageCategory.ERROR, "I/O error: " + e.getMessage(), null, -1, -1);
}
});
}
finally {
if (tempOutDir != null) {
FileUtil.delete(tempOutDir);
}
}
}
private static void removeAllFilesWithSameName(@NotNull final Module module, @NotNull File file, @NotNull String directoryPath) {
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
final VirtualFile genDir = LocalFileSystem.getInstance().findFileByPath(directoryPath);
if (vFile == null || genDir == null) {
return;
}
final Collection<VirtualFile> files =
FilenameIndex.getVirtualFilesByName(module.getProject(), file.getName(), module.getModuleScope(false));
final List<VirtualFile> filesToDelete = new ArrayList<VirtualFile>();
for (final VirtualFile f : files) {
if (f != vFile && VfsUtilCore.isAncestor(genDir, f, true)) {
filesToDelete.add(f);
}
}
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
for (VirtualFile f : filesToDelete) {
if (f.isValid() && f.exists()) {
try {
f.delete(module.getProject());
}
catch (IOException e) {
LOG.error(e);
}
}
}
}
});
}
});
}
private static void runAidl(@NotNull final AndroidFacet facet, @NotNull final CompileContext context) {
final Module module = facet.getModule();
final ModuleCompileScope moduleCompileScope = new ModuleCompileScope(module, false);
final VirtualFile[] files = moduleCompileScope.getFiles(AndroidIdlFileType.ourFileType, true);
final List<IdlAutogenerationItem> items = new ArrayList<IdlAutogenerationItem>();
for (final VirtualFile file : files) {
final IdlAutogenerationItem item = ApplicationManager.getApplication().runReadAction(new Computable<IdlAutogenerationItem>() {
@Nullable
@Override
public IdlAutogenerationItem compute() {
if (module.isDisposed() || module.getProject().isDisposed()) {
return null;
}
final IAndroidTarget target = facet.getConfiguration().getAndroidTarget();
if (target == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.specify.platform", module.getName()), null, -1, -1);
return null;
}
final String packageName = AndroidUtils.getPackageName(module, file);
if (packageName == null) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot compute package for file", file.getUrl(), -1, -1);
return null;
}
final String sourceRootPath = facet.getAidlGenSourceRootPath();
if (sourceRootPath == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.apt.gen.not.specified", module.getName()), null, -1, -1);
return null;
}
final VirtualFile[] sourceRoots = AndroidPackagingCompiler.getSourceRootsForModuleAndDependencies(module, false);
final String[] sourceRootOsPaths = AndroidCompileUtil.toOsPaths(sourceRoots);
final String outFileOsPath = FileUtil.toSystemDependentName(
sourceRootPath + '/' + packageName.replace('.', '/') + '/' + file.getNameWithoutExtension() + ".java");
return new IdlAutogenerationItem(file, target, outFileOsPath, sourceRootOsPaths, sourceRootPath, packageName);
}
});
if (item != null) {
items.add(item);
}
}
final Set<VirtualFile> filesToCheck = new HashSet<VirtualFile>();
for (IdlAutogenerationItem item : items) {
if (new File(FileUtil.toSystemDependentName(item.myFile.getPath())).exists()) {
filesToCheck.add(item.myFile);
}
}
if (!ensureFilesWritable(module.getProject(), filesToCheck)) {
return;
}
facet.clearAutogeneratedFiles(AndroidAutogeneratorMode.AIDL);
for (IdlAutogenerationItem item : items) {
final VirtualFile file = item.myFile;
final String fileOsPath = FileUtil.toSystemDependentName(file.getPath());
try {
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidIdl.execute(item.myTarget, fileOsPath, item.myOutFileOsPath, item.mySourceRootOsPaths));
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (module.getProject().isDisposed()) return;
for (CompilerMessageCategory category : messages.keySet()) {
List<String> messageList = messages.get(category);
for (String message : messageList) {
context.addMessage(category, message, file.getUrl(), -1, -1);
}
}
}
});
removeDuplicateClasses(module, item.myPackage, new File(item.myOutFileOsPath), item.myOutDirOsPath);
final VirtualFile genDir = LocalFileSystem.getInstance().findFileByPath(item.myOutDirOsPath);
if (genDir != null) {
genDir.refresh(false, true);
}
final VirtualFile outFile = LocalFileSystem.getInstance().findFileByPath(item.myOutFileOsPath);
if (outFile != null && outFile.exists()) {
facet.markFileAutogenerated(AndroidAutogeneratorMode.AIDL, outFile);
}
}
catch (final IOException e) {
LOG.info(e);
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (module.getProject().isDisposed()) return;
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), file.getUrl(), -1, -1);
}
});
}
}
}
private static void runRenderscript(@NotNull final AndroidFacet facet, @NotNull final CompileContext context) {
final Module module = facet.getModule();
final ModuleCompileScope moduleCompileScope = new ModuleCompileScope(module, false);
final VirtualFile[] files = moduleCompileScope.getFiles(AndroidRenderscriptFileType.INSTANCE, true);
facet.clearAutogeneratedFiles(AndroidAutogeneratorMode.RENDERSCRIPT);
for (final VirtualFile file : files) {
final RenderscriptAutogenerationItem item =
ApplicationManager.getApplication().runReadAction(new Computable<RenderscriptAutogenerationItem>() {
@Nullable
@Override
public RenderscriptAutogenerationItem compute() {
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
if (platform == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.specify.platform", module.getName()), null, -1, -1);
return null;
}
final IAndroidTarget target = platform.getTarget();
final String sdkLocation = platform.getSdk().getLocation();
final String packageName = AndroidUtils.getPackageName(module, file);
if (packageName == null) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot compute package for file", file.getUrl(), -1, -1);
return null;
}
final String resourceDirPath = AndroidRootUtil.getResourceDirPath(facet);
assert resourceDirPath != null;
final String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(module);
if (sourceRootPath == null) {
return null;
}
final String rawDirPath = resourceDirPath + '/' + AndroidConstants.FD_RES_RAW;
return new RenderscriptAutogenerationItem(sdkLocation, target, sourceRootPath, rawDirPath);
}
});
if (item == null) {
continue;
}
File tempOutDir = null;
try {
tempOutDir = FileUtil.createTempDirectory("android_renderscript_autogeneration", "tmp");
final Map<CompilerMessageCategory, List<String>> messages = AndroidRenderscriptCompiler.
launchRenderscriptCompiler(module.getProject(), item.mySdkLocation, item.myTarget, file, tempOutDir.getPath(), item.myRawDirPath);
if (messages.get(CompilerMessageCategory.ERROR).size() == 0) {
final List<File> newFiles = new ArrayList<File>();
moveAllFiles(tempOutDir, new File(item.myGenDirPath), newFiles);
for (File newFile : newFiles) {
final VirtualFile newVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(newFile);
if (newVFile != null) {
facet.markFileAutogenerated(AndroidAutogeneratorMode.RENDERSCRIPT, newVFile);
}
}
}
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (module.getProject().isDisposed()) {
return;
}
for (final CompilerMessageCategory category : messages.keySet()) {
final List<String> messageList = messages.get(category);
for (final String message : messageList) {
context.addMessage(category, message, file.getUrl(), -1, -1);
}
}
}
});
final VirtualFile genDir = LocalFileSystem.getInstance().findFileByPath(item.myGenDirPath);
if (genDir != null) {
genDir.refresh(false, true);
}
}
catch (final IOException e) {
LOG.info(e);
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (module.getProject().isDisposed()) return;
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), file.getUrl(), -1, -1);
}
});
}
finally {
if (tempOutDir != null) {
FileUtil.delete(tempOutDir);
}
}
}
}
private static void moveAllFiles(@NotNull File from, @NotNull File to, @NotNull Collection<File> newFiles) throws IOException {
if (from.isFile()) {
FileUtil.rename(from, to);
newFiles.add(to);
}
else {
final File[] children = from.listFiles();
if (children != null) {
for (File child : children) {
moveAllFiles(child, new File(to, child.getName()), newFiles);
}
}
}
}
private static boolean ensureFilesWritable(@NotNull final Project project, @NotNull final Collection<VirtualFile> filesToCheck) {
if (filesToCheck.size() == 0) {
return true;
}
final boolean[] run = {false};
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
run[0] = !project.isDisposed() &&
ReadonlyStatusHandler.ensureFilesWritable(project, filesToCheck.toArray(new VirtualFile[filesToCheck.size()]));
}
});
}
}, ModalityState.defaultModalityState());
return run[0];
}
private static void removeDuplicateClasses(@NotNull final Module module,
@NotNull final String aPackage,
@NotNull final File generatedFile,
@NotNull final String sourceRootPath) {
if (generatedFile.exists()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (module.getProject().isDisposed() || module.isDisposed()) {
return;
}
String className = FileUtil.getNameWithoutExtension(generatedFile);
AndroidCompileUtil.removeDuplicatingClasses(module, aPackage, className, generatedFile, sourceRootPath);
}
});
}
}
private static class AptAutogenerationItem {
final IAndroidTarget myTarget;
final int myPlatformToolsRevision;
final String myManifestFileOsPath;
final String myPackage;
final String myOutputDirOsPath;
final String[] myResDirOsPaths;
final boolean myLibrary;
final Map<String, String> myGenFileRelPath2package;
private AptAutogenerationItem(@NotNull IAndroidTarget target,
int platformToolsRevision,
@NotNull String manifestFileOsPath,
@NotNull String aPackage,
@NotNull String outputDirOsPath,
@NotNull String[] resDirOsPaths,
boolean library,
@NotNull Map<String, String> genFileRelPath2package) {
myTarget = target;
myPlatformToolsRevision = platformToolsRevision;
myManifestFileOsPath = manifestFileOsPath;
myPackage = aPackage;
myOutputDirOsPath = outputDirOsPath;
myResDirOsPaths = resDirOsPaths;
myLibrary = library;
myGenFileRelPath2package = genFileRelPath2package;
}
}
private static class IdlAutogenerationItem {
final VirtualFile myFile;
final IAndroidTarget myTarget;
final String myOutFileOsPath;
final String[] mySourceRootOsPaths;
final String myOutDirOsPath;
final String myPackage;
private IdlAutogenerationItem(@NotNull VirtualFile file,
@NotNull IAndroidTarget target,
@NotNull String outFileOsPath,
@NotNull String[] sourceRootOsPaths,
@NotNull String outDirOsPath,
@NotNull String aPackage) {
myFile = file;
myTarget = target;
myOutFileOsPath = outFileOsPath;
mySourceRootOsPaths = sourceRootOsPaths;
myOutDirOsPath = outDirOsPath;
myPackage = aPackage;
}
}
private static class RenderscriptAutogenerationItem {
final String mySdkLocation;
final IAndroidTarget myTarget;
final String myGenDirPath;
final String myRawDirPath;
private RenderscriptAutogenerationItem(@NotNull String sdkLocation,
@NotNull IAndroidTarget target,
@NotNull String genDirPath,
@NotNull String rawDirPath) {
mySdkLocation = sdkLocation;
myTarget = target;
myGenDirPath = genDirPath;
myRawDirPath = rawDirPath;
}
}
}
@@ -0,0 +1,8 @@
package org.jetbrains.android.compiler;
/**
* @author Eugene.Kudelevsky
*/
public enum AndroidAutogeneratorMode {
AAPT, AIDL, RENDERSCRIPT
}
@@ -17,6 +17,8 @@ package org.jetbrains.android.compiler;
import com.android.resources.ResourceType;
import com.intellij.CommonBundle;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.compiler.impl.CompileContextImpl;
import com.intellij.compiler.impl.ModuleCompileScope;
import com.intellij.compiler.options.CompileStepBeforeRun;
@@ -27,6 +29,8 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.Compiler;
import com.intellij.openapi.compiler.options.ExcludeEntryDescription;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
@@ -35,7 +39,6 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
@@ -46,8 +49,8 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.AndroidProjectComponent;
import org.jetbrains.android.dom.resources.Attr;
import org.jetbrains.android.dom.resources.DeclareStyleable;
import org.jetbrains.android.dom.resources.ResourceElement;
@@ -58,7 +61,9 @@ import org.jetbrains.android.fileTypes.AndroidIdlFileType;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.resourceManagers.LocalResourceManager;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -77,16 +82,16 @@ import java.util.regex.Pattern;
public class AndroidCompileUtil {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidCompileUtil");
private static Pattern R_PATTERN = Pattern.compile("R(\\$.*)?\\.class");
private static final Pattern ourMessagePattern = Pattern.compile("(.+):(\\d+):.+");
private static final Key<Boolean> RELEASE_BUILD_KEY = new Key<Boolean>("RELEASE_BUILD_KEY");
@NonNls private static final String RESOURCES_CACHE_DIR_NAME = "res-cache";
@NonNls private static final String GEN_MODULE_PREFIX = "~generated_";
@NonNls private static final String PROGUARD_CFG_FILE_NAME = "proguard.cfg";
@NonNls public static final String CLASSES_JAR_FILE_NAME = "classes.jar";
@NonNls
private static final String[] SCALA_TEST_CONFIGURATIONS =
{"ScalaTestRunConfiguration", "SpecsRunConfiguration", "Specs2RunConfiguration"};
@@ -94,6 +99,29 @@ public class AndroidCompileUtil {
private AndroidCompileUtil() {
}
@NotNull
public static <T> Map<CompilerMessageCategory, T> toCompilerMessageCategoryKeys(@NotNull Map<AndroidCompilerMessageKind, T> map) {
final Map<CompilerMessageCategory, T> result = new HashMap<CompilerMessageCategory, T>();
for (Map.Entry<AndroidCompilerMessageKind, T> entry : map.entrySet()) {
final AndroidCompilerMessageKind key = entry.getKey();
final T value = entry.getValue();
switch (key) {
case ERROR:
result.put(CompilerMessageCategory.ERROR, value);
break;
case INFORMATION:
result.put(CompilerMessageCategory.INFORMATION, value);
break;
case WARNING:
result.put(CompilerMessageCategory.WARNING, value);
break;
}
}
return result;
}
@Nullable
public static VirtualFile getProguardConfigFile(@NotNull AndroidFacet facet) {
final VirtualFile root = AndroidRootUtil.getMainContentRoot(facet);
@@ -166,7 +194,7 @@ public class AndroidCompileUtil {
if (root == anchor) {
return;
}
VirtualFile parent = anchor.getParent();
if (parent == null) {
return;
@@ -191,7 +219,7 @@ public class AndroidCompileUtil {
return;
}
Set<VirtualFile> rootsToExclude = new HashSet<VirtualFile>();
collectChildrenRecursively(excludedRoot, root, rootsToExclude);
collectChildrenRecursively(excludedRoot, root, rootsToExclude);
final ModifiableRootModel model = manager.getModifiableModel();
ContentEntry contentEntry = findContentEntryForRoot(model, excludedRoot);
if (contentEntry != null) {
@@ -218,7 +246,7 @@ public class AndroidCompileUtil {
}
});
}
@NotNull
private static String getGenModuleName(@NotNull Module module) {
return GEN_MODULE_PREFIX + module.getName();
@@ -259,17 +287,40 @@ public class AndroidCompileUtil {
if (root != null) {
final ModuleRootManager manager = ModuleRootManager.getInstance(module);
unexcludeRootIfNeccessary(root, manager);
boolean markedAsSource = false;
for (VirtualFile existingRoot : manager.getSourceRoots()) {
if (existingRoot == root) return;
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
addSourceRoot(manager, root);
if (existingRoot == root) {
markedAsSource = true;
}
});
}
if (!markedAsSource) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
addSourceRoot(manager, root);
}
});
}
excludeFromCompilation(project, root);
}
}
private static void excludeFromCompilation(@NotNull Project project, @NotNull VirtualFile dir) {
final ExcludedEntriesConfiguration configuration =
((CompilerConfigurationImpl)CompilerConfiguration.getInstance(project)).getExcludedEntriesConfiguration();
for (ExcludeEntryDescription description : configuration.getExcludeEntryDescriptions()) {
if (description.getVirtualFile() == dir) {
return;
}
}
configuration.addExcludeEntryDescription(new ExcludeEntryDescription(dir, true, false, project));
}
private static void removeGenModule(@NotNull final Module libModule) {
final String genModuleName = getGenModuleName(libModule);
final ModuleManager moduleManager = ModuleManager.getInstance(libModule.getProject());
@@ -295,7 +346,7 @@ public class AndroidCompileUtil {
}
final VirtualFile moduleFile = genModule.getModuleFile();
moduleManager.disposeModule(genModule);
if (moduleFile != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
@@ -338,132 +389,70 @@ public class AndroidCompileUtil {
return contentEntry;
}
public static void generate(final Module module, final GeneratingCompiler compiler, boolean withDependentModules) {
public static void generate(final Module module, final AndroidAutogeneratorMode mode, boolean withDependentModules) {
if (withDependentModules) {
Set<Module> modules = new HashSet<Module>();
collectModules(module, modules, ModuleManager.getInstance(module.getProject()).getModules());
for (Module module1 : modules) {
generate(module1, compiler);
generate(module1, mode);
}
}
else {
generate(module, compiler);
generate(module, mode);
}
}
public static void generate(final Module module, final GeneratingCompiler compiler) {
public static void generate(final Module module, final AndroidAutogeneratorMode mode) {
final AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null) {
facet.scheduleSourceRegenerating(compiler);
facet.scheduleSourceRegenerating(mode);
}
}
public static void doGenerate(final Module module, final GeneratingCompiler compiler) {
public static boolean doGenerate(final Module module, final AndroidAutogeneratorMode mode) {
final Project project = module.getProject();
final AndroidProjectComponent component = ApplicationManager.getApplication().runReadAction(new Computable<AndroidProjectComponent>() {
@Nullable
@Override
public AndroidProjectComponent compute() {
return !project.isDisposed() ? project.getComponent(AndroidProjectComponent.class) : null;
}
});
if (component == null) {
return;
}
component.runIfNotInCompilation(new Runnable() {
@Override
assert !ApplicationManager.getApplication().isDispatchThread();
final CompileContext[] contextWrapper = new CompileContext[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
assert !ApplicationManager.getApplication().isDispatchThread();
final CompileContext[] contextWrapper = new CompileContext[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (project.isDisposed()) return;
CompilerTask task = new CompilerTask(project, true, "Android auto-generation", true);
CompileScope scope = new ModuleCompileScope(module, false);
contextWrapper[0] = new CompileContextImpl(project, task, scope, null, false, false);
}
});
generate(compiler, contextWrapper[0]);
if (project.isDisposed()) return;
CompilerTask task = new CompilerTask(project, true, "Android auto-generation", true);
CompileScope scope = new ModuleCompileScope(module, false);
contextWrapper[0] = new CompileContextImpl(project, task, scope, null, false, false);
}
});
generate(module, mode, contextWrapper[0]);
return contextWrapper[0].getMessages(CompilerMessageCategory.ERROR).length == 0;
}
public static boolean isModuleAffected(CompileContext context, Module module) {
return ArrayUtil.find(context.getCompileScope().getAffectedModules(), module) >= 0;
}
public static void generate(GeneratingCompiler compiler, final CompileContext context) {
public static void generate(final Module module, AndroidAutogeneratorMode mode, final CompileContext context) {
if (context == null) {
return;
}
final Set<Module> affectedModules = new HashSet<Module>();
Collections.addAll(affectedModules, context.getCompileScope().getAffectedModules());
final AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet == null) {
return;
}
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
for (Module module : affectedModules) {
if (module.isDisposed() || module.getProject().isDisposed()) {
continue;
}
final AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null) {
AndroidCompileUtil.createGenModulesAndSourceRoots(facet);
}
if (facet.getModule().isDisposed() || facet.getModule().getProject().isDisposed()) {
return;
}
AndroidCompileUtil.createGenModulesAndSourceRoots(facet);
}
}, ModalityState.defaultModalityState());
List<GeneratingCompiler.GenerationItem> itemsToGenerate = new ArrayList<GeneratingCompiler.GenerationItem>();
for (GeneratingCompiler.GenerationItem item : compiler.getGenerationItems(context)) {
if (affectedModules.contains(item.getModule())) {
itemsToGenerate.add(item);
}
}
GeneratingCompiler.GenerationItem[] items = itemsToGenerate.toArray(new GeneratingCompiler.GenerationItem[itemsToGenerate.size()]);
final boolean[] run = {true};
final VirtualFile[] files = getFilesToCheckReadonlyStatus(items);
if (files.length > 0) {
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final Project project = context.getProject();
run[0] = !project.isDisposed() && ReadonlyStatusHandler.ensureFilesWritable(project, files);
}
});
}
}, ModalityState.defaultModalityState());
}
if (run[0]) {
compiler.generate(context, items, null);
}
}
private static VirtualFile[] getFilesToCheckReadonlyStatus(GeneratingCompiler.GenerationItem[] items) {
List<VirtualFile> filesToCheck = new ArrayList<VirtualFile>();
for (GeneratingCompiler.GenerationItem item : items) {
if (item instanceof AndroidAptCompiler.AptGenerationItem) {
final Set<File> generatedFiles = ((AndroidAptCompiler.AptGenerationItem)item).getGeneratedFiles().keySet();
for (File generatedFile : generatedFiles) {
if (generatedFile.exists()) {
VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(generatedFile);
if (generatedVFile != null) {
filesToCheck.add(generatedVFile);
}
}
}
}
}
return VfsUtil.toVirtualFileArray(filesToCheck);
AndroidAutogenerator.run(mode, facet, context);
}
private static void collectModules(Module module, Set<Module> result, Module[] allModules) {
@@ -530,15 +519,15 @@ public class AndroidCompileUtil {
final Project project = facet.getModule().getProject();
final IntermediateOutputCompiler pngFilesCachingCompiler =
collectResCacheDirs ? Extensions.findExtension(Compiler.EP_NAME, project, AndroidPngFilesCachingCompiler.class) : null;
if (collectResCacheDirs) {
assert pngFilesCachingCompiler != null;
}
final List<String> result = new ArrayList<String>();
doCollectResourceDirs(facet, collectResCacheDirs, result, context);
for (AndroidFacet depFacet : AndroidUtils.getAllAndroidDependencies(facet.getModule(), true)) {
doCollectResourceDirs(depFacet, collectResCacheDirs, result, context);
}
@@ -623,11 +612,11 @@ public class AndroidCompileUtil {
public static boolean isFullBuild(@NotNull CompileContext context) {
final RunConfiguration runConfiguration = CompileStepBeforeRun.getRunConfiguration(context);
if (runConfiguration == null) {
return true;
}
if (runConfiguration instanceof JUnitConfiguration) {
return false;
}
@@ -802,7 +791,7 @@ public class AndroidCompileUtil {
boolean packRClasses,
@NotNull List<Pair<File, String>> files)
throws IOException {
if (file.isDirectory()) {
final File[] children = file.listFiles();
@@ -816,13 +805,13 @@ public class AndroidCompileUtil {
if (!FileUtil.getExtension(file.getName()).equals("class")) {
return;
}
if (!packRClasses && R_PATTERN.matcher(file.getName()).matches()) {
return;
}
final String rootPath = rootDirectory.getAbsolutePath();
String path = file.getAbsolutePath();
path = FileUtil.toSystemIndependentName(path.substring(rootPath.length()));
if (path.charAt(0) == '/') {
@@ -861,4 +850,12 @@ public class AndroidCompileUtil {
}
return classFilesDirOsPaths;
}
// can't be invoked from dispatch thread
@NotNull
public static Map<CompilerMessageCategory, List<String>> execute(String... argv) throws IOException {
assert !ApplicationManager.getApplication().isDispatchThread();
final Map<AndroidCompilerMessageKind, List<String>> messages = ExecutionUtil.doExecute(argv);
return toCompilerMessageCategoryKeys(messages);
}
}
@@ -17,18 +17,15 @@ package org.jetbrains.android.compiler;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.facet.FacetManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.android.compiler.tools.AndroidIdl;
import org.jetbrains.android.facet.AndroidFacet;
@@ -39,7 +36,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -59,6 +55,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
myProject = project;
}
@Nullable
@Override
public VirtualFile getPresentableFile(CompileContext context, Module module, VirtualFile outputRoot, VirtualFile generatedFile) {
return null;
@@ -71,23 +68,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
public GenerationItem[] generate(CompileContext context, GenerationItem[] items, VirtualFile outputRootDirectory) {
if (items != null && items.length > 0) {
context.getProgressIndicator().setText("Generating AIDL files...");
//Application application = ApplicationManager.getApplication();
GenerationItem[] generationItems = /*application.runReadAction(new GenerateAction(context, items))*/ doGenerate(context, items);
List<VirtualFile> generatedVFiles = new ArrayList<VirtualFile>();
for (GenerationItem item : generationItems) {
File generatedFile = ((IdlGenerationItem)item).myGeneratedFile;
if (generatedFile != null) {
CompilerUtil.refreshIOFile(generatedFile);
VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(generatedFile);
if (generatedVFile != null) {
generatedVFiles.add(generatedVFile);
}
}
}
if (context instanceof CompileContextEx) {
((CompileContextEx)context).markGenerated(generatedVFiles);
}
return generationItems;
return doGenerate(context, items, outputRootDirectory);
}
return EMPTY_GENERATION_ITEM_ARRAY;
}
@@ -103,7 +84,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
@Nullable
public ValidityState createValidityState(DataInput is) throws IOException {
return null;
return TimestampValidityState.load(is);
}
private final static class IdlGenerationItem implements GenerationItem {
@@ -111,13 +92,10 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
final VirtualFile myFile;
final boolean myTestSource;
final IAndroidTarget myAndroidTarget;
final File myGeneratedFile;
final String myPackageName;
final String mySourceRootPath;
public IdlGenerationItem(@NotNull Module module,
@NotNull VirtualFile file,
@NotNull String sourceRootPath,
boolean testSource,
@NotNull IAndroidTarget androidTarget,
@NotNull String packageName) {
@@ -126,19 +104,16 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
myTestSource = testSource;
myAndroidTarget = androidTarget;
myPackageName = packageName;
mySourceRootPath = sourceRootPath;
myGeneratedFile =
new File(sourceRootPath, packageName.replace('.', File.separatorChar) + File.separator + file.getNameWithoutExtension() + ".java");
}
@Nullable
public String getPath() {
return null;
return myPackageName.replace('.', '/') + '/' + myFile.getNameWithoutExtension() + ".java";
}
@Nullable
public ValidityState getValidityState() {
return null;
return new TimestampValidityState(myFile.getTimeStamp());
}
public Module getModule() {
@@ -198,21 +173,11 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
return;
}
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
IdlGenerationItem generationItem =
new IdlGenerationItem(module, file, sourceRootPath, fileIndex.isInTestSourceContent(file), target, packageName);
if (myContext.isMake()) {
File generatedFile = generationItem.myGeneratedFile;
if (generatedFile == null || !generatedFile.exists() || generatedFile.lastModified() <= file.getModificationCount()) {
items.add(generationItem);
}
}
else {
items.add(generationItem);
}
items.add(new IdlGenerationItem(module, file, fileIndex.isInTestSourceContent(file), target, packageName));
}
}
private static GenerationItem[] doGenerate(final CompileContext context, GenerationItem[] items) {
private static GenerationItem[] doGenerate(final CompileContext context, GenerationItem[] items, VirtualFile outputRootDirectory) {
if (context.getProject().isDisposed()) {
return EMPTY_GENERATION_ITEM_ARRAY;
}
@@ -229,8 +194,12 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
VirtualFile[] sourceRoots = AndroidPackagingCompiler.getSourceRootsForModuleAndDependencies(idlItem.myModule, false);
final String[] sourceRootPaths = AndroidCompileUtil.toOsPaths(sourceRoots);
final Map<CompilerMessageCategory, List<String>> messages = AndroidIdl
.execute(idlItem.myAndroidTarget, idlItem.myFile.getPath(), idlItem.myGeneratedFile.getPath(), sourceRootPaths);
final String outFilePath = FileUtil.toSystemDependentName(
outputRootDirectory.getPath() + '/' + idlItem.myPackageName.replace('.', '/') + '/' +
idlItem.myFile.getNameWithoutExtension() + ".java");
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidIdl.execute(idlItem.myAndroidTarget, idlItem.myFile.getPath(), outFilePath, sourceRootPaths));
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
@@ -241,17 +210,6 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
if (messages.get(CompilerMessageCategory.ERROR).isEmpty()) {
results.add(idlItem);
}
if (idlItem.myGeneratedFile.exists()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (idlItem.myModule.getProject().isDisposed()) return;
String className = FileUtil.getNameWithoutExtension(idlItem.myGeneratedFile);
AndroidCompileUtil.removeDuplicatingClasses(idlItem.myModule, idlItem.myPackageName, className,
idlItem.myGeneratedFile.exists() ? idlItem.myGeneratedFile : null,
idlItem.mySourceRootPath);
}
});
}
}
catch (final IOException e) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -31,7 +31,7 @@ import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.maven.AndroidMavenProvider;
import org.jetbrains.android.maven.AndroidMavenUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.project.MavenProject;
@@ -144,13 +144,13 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler {
myModule = module;
myPackage = aPackage;
myGeneratedFile =
new File(sourceRootPath, aPackage.replace('.', File.separatorChar) + File.separator + AndroidUtils.R_JAVA_FILENAME);
new File(sourceRootPath, aPackage.replace('.', File.separatorChar) + File.separator + AndroidCommonUtils.R_JAVA_FILENAME);
mySourceRootPath = sourceRootPath;
}
@Nullable
public String getPath() {
return myPackage.replace('.', '/') + '/' + AndroidUtils.R_JAVA_FILENAME;
return myPackage.replace('.', '/') + '/' + AndroidCommonUtils.R_JAVA_FILENAME;
}
public ValidityState getValidityState() {
@@ -98,9 +98,9 @@ public class AndroidPngFilesCachingCompiler implements SourceGeneratingCompiler
if (resCacheDirOsPath == null) {
continue;
}
final Map<CompilerMessageCategory, List<String>> messages =
AndroidApt.crunch(item.getTarget(), Collections.singletonList(resDirOsPath), resCacheDirOsPath);
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidApt.crunch(item.getTarget(), Collections.singletonList(resDirOsPath), resCacheDirOsPath));
AndroidCompileUtil.addMessages(context, messages, null);
if (context.getMessages(CompilerMessageCategory.ERROR).length == 0) {
processedItems.add(item);
@@ -19,7 +19,10 @@ import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.CompilationStatusAdapter;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileTask;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.compiler.options.ExcludeEntryDescription;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.diagnostic.Logger;
@@ -30,16 +33,13 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.android.AndroidProjectComponent;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Arrays;
@@ -50,20 +50,12 @@ import java.util.Set;
* @author Eugene.Kudelevsky
*/
public class AndroidPrecompileTask implements CompileTask {
private final AndroidProjectComponent myOwner;
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidPrecompileTask");
public AndroidPrecompileTask(@NotNull AndroidProjectComponent owner) {
myOwner = owner;
}
@Override
public boolean execute(CompileContext context) {
final Project project = context.getProject();
myOwner.setCompilationStarted();
ExcludedEntriesConfiguration configuration =
((CompilerConfigurationImpl)CompilerConfiguration.getInstance(project)).getExcludedEntriesConfiguration();
@@ -85,7 +77,7 @@ public class AndroidPrecompileTask implements CompileTask {
}, indicator != null ? indicator.getModalityState() : ModalityState.NON_MODAL);
if (context.isRebuild()) {
clearGenRootsAndResCache(facet, context);
clearResCache(facet, context);
}
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
@@ -99,7 +91,7 @@ public class AndroidPrecompileTask implements CompileTask {
excludeAllSourceRoots(module, configuration, addedEntries);
}
else {
unexcludeAllSourceRoots(module, configuration);
unexcludeAllSourceRoots(facet, configuration);
}
}
}
@@ -108,28 +100,11 @@ public class AndroidPrecompileTask implements CompileTask {
LOG.debug("Files excluded by Android: " + addedEntries.size());
CompilerManager.getInstance(project).addCompilationStatusListener(new MyCompilationStatusListener(project, addedEntries), project);
}
CompilerManager.getInstance(project).addCompilationStatusListener(new CompilationStatusAdapter() {
@Override
public void compilationFinished(boolean aborted, int errors, int warnings, final CompileContext compileContext) {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
myOwner.setCompilationFinished();
}
});
}
}, project);
return true;
}
private static void clearGenRootsAndResCache(@NotNull AndroidFacet facet, @NotNull CompileContext context) {
private static void clearResCache(@NotNull AndroidFacet facet, @NotNull CompileContext context) {
final Module module = facet.getModule();
removeAllPackages(AndroidRootUtil.getRenderscriptGenSourceRootPath(module), context);
removeAllPackages(facet.getAptGenSourceRootPath(), context);
removeAllPackages(facet.getAidlGenSourceRootPath(), context);
final String dirPath = AndroidCompileUtil.findResourcesCacheDirectory(module, false, null);
if (dirPath != null) {
@@ -139,38 +114,36 @@ public class AndroidPrecompileTask implements CompileTask {
}
}
}
private static void removeAllPackages(@Nullable String sourceRootPath, @NotNull CompileContext context) {
final File sourceRoot = new File(sourceRootPath);
final File[] children = sourceRoot.listFiles();
if (children != null) {
for (File child : children) {
if (child.isDirectory() &&
child.getName() != null &&
StringUtil.isJavaIdentifier(child.getName())) {
if (!FileUtil.delete(child)) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot delete file " + child.getAbsolutePath(),
null, -1, -1);
}
}
}
}
final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(sourceRoot);
if (vFile != null) {
vFile.refresh(false, true);
}
}
private static void unexcludeAllSourceRoots(Module module,
private static void unexcludeAllSourceRoots(AndroidFacet facet,
ExcludedEntriesConfiguration configuration) {
final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots();
final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(facet.getModule()).getSourceRoots();
final Set<VirtualFile> sourceRootSet = new HashSet<VirtualFile>();
sourceRootSet.addAll(Arrays.asList(sourceRoots));
final String aidlGenSourceRootPath = facet.getAidlGenSourceRootPath();
if (aidlGenSourceRootPath != null) {
final VirtualFile aidlGenSourceRoot = LocalFileSystem.getInstance().findFileByPath(aidlGenSourceRootPath);
if (aidlGenSourceRoot != null) {
sourceRootSet.remove(aidlGenSourceRoot);
}
}
final String aptGenSourceRootPath = facet.getAptGenSourceRootPath();
if (aptGenSourceRootPath != null) {
final VirtualFile aptGenSourceRoot = LocalFileSystem.getInstance().findFileByPath(aptGenSourceRootPath);
if (aptGenSourceRoot != null) {
sourceRootSet.remove(aptGenSourceRoot);
}
}
final VirtualFile rsGenRoot = AndroidRootUtil.getRenderscriptGenDir(facet.getModule());
if (rsGenRoot != null) {
sourceRootSet.remove(rsGenRoot);
}
final ExcludeEntryDescription[] descriptions = configuration.getExcludeEntryDescriptions();
configuration.removeAllExcludeEntryDescriptions();
@@ -23,14 +23,19 @@ import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.util.*;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Eugene.Kudelevsky
@@ -250,8 +255,8 @@ public class AndroidProguardCompiler implements ClassPostProcessingCompiler {
commands.add(quotePath(new File(logDirOutputOsPath, "mapping.txt").getAbsolutePath()));
}
LOG.info(AndroidUtils.command2string(commands));
return ExecutionUtil.execute(ArrayUtil.toStringArray(commands));
LOG.info(AndroidCommonUtils.command2string(commands));
return AndroidCompileUtil.execute(ArrayUtil.toStringArray(commands));
}
private static String quotePath(String path) {
@@ -3,7 +3,6 @@ package org.jetbrains.android.compiler;
import com.android.AndroidConstants;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.facet.FacetManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
@@ -19,14 +18,15 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -60,68 +60,64 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
}
final VirtualFile[] files = context.getProjectCompileScope().getFiles(AndroidRenderscriptFileType.INSTANCE, true);
final List<GenerationItem> items = new ArrayList<GenerationItem>(files.length);
for (final VirtualFile file : files) {
final Map<Module, Collection<VirtualFile>> module2files = new HashMap<Module, Collection<VirtualFile>>();
for (VirtualFile file : files) {
final Module module = context.getModuleByFile(file);
final AndroidFacet facet = FacetManager.getInstance(module).getFacetByType(AndroidFacet.ID);
if (facet != null) {
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
if (platform == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.specify.platform", module.getName()), null, -1, -1);
continue;
if (module != null) {
Collection<VirtualFile> filesForModule = module2files.get(module);
if (filesForModule == null) {
filesForModule = new ArrayList<VirtualFile>();
module2files.put(module, filesForModule);
}
final IAndroidTarget target = platform.getTarget();
final String sdkLocation = platform.getSdk().getLocation();
final String packageName = AndroidUtils.getPackageName(module, file);
if (packageName == null) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot compute package for file", file.getUrl(), -1, -1);
continue;
}
final String resourceDirPath = AndroidRootUtil.getResourceDirPath(facet);
assert resourceDirPath != null;
addItem(context, file, facet, resourceDirPath, sdkLocation, target, packageName, items);
if (facet.getConfiguration().LIBRARY_PROJECT) {
final HashSet<Module> usingModules = new HashSet<Module>();
AndroidUtils.collectModulesDependingOn(module, usingModules);
for (final Module module1 : usingModules) {
final AndroidFacet facet1 = AndroidFacet.getInstance(module1);
if (facet1 != null) {
addItem(context, file, facet1, resourceDirPath, sdkLocation, target, packageName, items);
}
}
}
filesForModule.add(file);
}
}
final List<GenerationItem> items = new ArrayList<GenerationItem>(files.length);
for (Map.Entry<Module, Collection<VirtualFile>> entry : module2files.entrySet()) {
final Module module = entry.getKey();
final AndroidFacet facet = FacetManager.getInstance(module).getFacetByType(AndroidFacet.ID);
if (facet == null) {
continue;
}
final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform();
if (platform == null) {
context.addMessage(CompilerMessageCategory.ERROR,
AndroidBundle.message("android.compilation.error.specify.platform", module.getName()), null, -1, -1);
continue;
}
final IAndroidTarget target = platform.getTarget();
final String sdkLocation = platform.getSdk().getLocation();
final String resourceDirPath = AndroidRootUtil.getResourceDirPath(facet);
assert resourceDirPath != null;
addItem(entry.getValue(), facet, resourceDirPath, sdkLocation, target, items);
}
return items.toArray(new GenerationItem[items.size()]);
}
});
}
private static void addItem(@NotNull final CompileContext context,
@NotNull final VirtualFile sourceFile,
private static void addItem(@NotNull final Collection<VirtualFile> sourceFiles,
@NotNull final AndroidFacet facet,
@NotNull final String resourceDirPath,
@NotNull String sdkLocation,
@NotNull final IAndroidTarget target,
@NotNull final String packageName,
@NotNull final List<GenerationItem> items) {
final Module module = facet.getModule();
final String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(module);
if (sourceRootPath == null) {
return;
}
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(context.getProject()).getFileIndex();
final String rawDirPath = resourceDirPath + '/' + AndroidConstants.FD_RES_RAW;
items.add(new MyGenerationItem(module, sourceFile, sourceRootPath, packageName, rawDirPath, fileIndex.isInTestSourceContent(sourceFile),
sdkLocation, target));
items.add(new MyGenerationItem(module, sourceFiles, rawDirPath, sdkLocation, target));
}
@Override
@@ -133,19 +129,13 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
}
context.getProgressIndicator().setText("Compiling RenderScript files...");
final GenerationItem[] generationItems = doGenerate(context, items);
final GenerationItem[] generationItems = doGenerate(context, items, outputRootDirectory);
final Set<VirtualFile> generatedVFiles = new HashSet<VirtualFile>();
final HashSet<VirtualFile> visited = new HashSet<VirtualFile>();
for (GenerationItem item : generationItems) {
final MyGenerationItem genItem = (MyGenerationItem)item;
final File genDir = new File(genItem.myGenRootPath);
CompilerUtil.refreshIODirectories(Arrays.asList(genDir));
final VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(genDir);
if (generatedVFile != null) {
AndroidUtils.collectFiles(generatedVFile, visited, generatedVFiles);
}
}
outputRootDirectory.refresh(false, true);
AndroidUtils.collectFiles(outputRootDirectory, visited, generatedVFiles);
if (context instanceof CompileContextEx) {
((CompileContextEx)context).markGenerated(generatedVFiles);
}
@@ -169,11 +159,27 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
return new MyValidityState(in);
}
private static GenerationItem[] doGenerate(@NotNull final CompileContext context, @NotNull final GenerationItem[] items) {
private static GenerationItem[] doGenerate(@NotNull final CompileContext context,
@NotNull final GenerationItem[] items,
VirtualFile outputRootDirectory) {
if (context.getProject().isDisposed()) {
return EMPTY_GENERATION_ITEM_ARRAY;
}
// we have one item per module there, so clear output directory
final String genRootPath = FileUtil.toSystemDependentName(outputRootDirectory.getPath());
final File genRootDir = new File(genRootPath);
if (genRootDir.exists()) {
if (!FileUtil.delete(genRootDir)) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot delete directory " + genRootPath, null, -1, -1);
return EMPTY_GENERATION_ITEM_ARRAY;
}
if (!genRootDir.mkdir()) {
context.addMessage(CompilerMessageCategory.ERROR, "Cannot create directory " + genRootPath, null, -1, -1);
return EMPTY_GENERATION_ITEM_ARRAY;
}
}
final List<GenerationItem> results = new ArrayList<GenerationItem>(items.length);
for (final GenerationItem item : items) {
if (item instanceof MyGenerationItem) {
@@ -183,33 +189,35 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
continue;
}
try {
final Map<CompilerMessageCategory, List<String>> messages = launchRenderscriptCompiler(context.getProject(),
genItem.mySdkLocation,
genItem.myAndroidTarget,
genItem.mySourceFile,
genItem.myGenRootPath,
genItem.myRawDirPath);
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (context.getProject().isDisposed()) {
return;
for (final VirtualFile sourceFile : genItem.myFiles) {
try {
final Map<CompilerMessageCategory, List<String>> messages = launchRenderscriptCompiler(context.getProject(),
genItem.mySdkLocation,
genItem.myAndroidTarget,
sourceFile,
genRootPath,
genItem.myRawDirPath);
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (context.getProject().isDisposed()) {
return;
}
addMessages(context, messages, sourceFile.getUrl());
}
addMessages(context, messages, genItem.mySourceFile.getUrl());
}
});
});
if (messages.get(CompilerMessageCategory.ERROR).isEmpty()) {
results.add(genItem);
}
}
catch (final IOException e) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (context.getProject().isDisposed()) return;
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), genItem.mySourceFile.getUrl(), -1, -1);
if (messages.get(CompilerMessageCategory.ERROR).isEmpty()) {
results.add(genItem);
}
});
}
catch (final IOException e) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (context.getProject().isDisposed()) return;
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), sourceFile.getUrl(), -1, -1);
}
});
}
}
}
}
@@ -227,12 +235,12 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
}
}
private static Map<CompilerMessageCategory, List<String>> launchRenderscriptCompiler(@NotNull Project project,
@NotNull final String sdkLocation,
@NotNull IAndroidTarget target,
@NotNull final VirtualFile sourceFile,
@NotNull final String genFolderPath,
@NotNull final String rawDirPath)
static Map<CompilerMessageCategory, List<String>> launchRenderscriptCompiler(@NotNull Project project,
@NotNull final String sdkLocation,
@NotNull IAndroidTarget target,
@NotNull final VirtualFile sourceFile,
@NotNull final String genFolderPath,
@NotNull final String rawDirPath)
throws IOException {
final List<String> command = new ArrayList<String>();
command.add(
@@ -260,8 +268,8 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
command.add("-MD");
command.add(sourceFilePath);
LOG.info(AndroidUtils.command2string(command));
return ExecutionUtil.execute(ArrayUtil.toStringArray(command));
LOG.info(AndroidCommonUtils.command2string(command));
return AndroidCompileUtil.execute(ArrayUtil.toStringArray(command));
}
@Nullable
@@ -288,43 +296,30 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
private static class MyGenerationItem implements GenerationItem {
final Module myModule;
final String mySdkLocation;
final VirtualFile mySourceFile;
final boolean myTestSource;
final Collection<VirtualFile> myFiles;
final IAndroidTarget myAndroidTarget;
final String myGenRootPath;
final String myRawDirPath;
final String myPackageName;
final boolean myFileExists;
final File myParentDirectory;
public MyGenerationItem(@NotNull Module module,
@NotNull VirtualFile sourceFile,
@NotNull String genRootPath,
@NotNull String packageName,
@NotNull Collection<VirtualFile> files,
@NotNull String rawDirPath,
boolean testSource,
@NotNull String sdkLocation,
@NotNull IAndroidTarget target) {
myModule = module;
mySourceFile = sourceFile;
myFiles = files;
myRawDirPath = rawDirPath;
myTestSource = testSource;
mySdkLocation = sdkLocation;
myAndroidTarget = target;
myGenRootPath = genRootPath;
myPackageName = packageName;
myParentDirectory = new File(myGenRootPath, myPackageName.replace('.', File.separatorChar));
myFileExists = myParentDirectory.exists();
}
@Nullable
public String getPath() {
return null;
return "";
}
@Nullable
public ValidityState getValidityState() {
return new MyValidityState(mySourceFile, myFileExists);
return new MyValidityState(myFiles);
}
public Module getModule() {
@@ -332,22 +327,28 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
}
public boolean isTestSource() {
return myTestSource;
return false;
}
}
private static class MyValidityState implements ValidityState {
private final long myTimestamp;
private final boolean myFileExists;
public MyValidityState(@NotNull DataInput in) throws IOException {
myTimestamp = in.readLong();
myFileExists = true;
private final Map<String, Long> myTimestamps = new HashMap<String, Long>();
MyValidityState(DataInput in) throws IOException {
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final String path = in.readUTF();
final long timestamp = in.readLong();
myTimestamps.put(path, timestamp);
}
}
public MyValidityState(@NotNull VirtualFile file, boolean fileExists) {
myTimestamp = file.getTimeStamp();
myFileExists = fileExists;
MyValidityState(@NotNull Collection<VirtualFile> files) {
for (VirtualFile file : files) {
myTimestamps.put(file.getPath(), file.getTimeStamp());
}
}
@Override
@@ -355,15 +356,17 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
if (!(otherState instanceof MyValidityState)) {
return false;
}
final MyValidityState st = (MyValidityState)otherState;
return myTimestamp == st.myTimestamp &&
myFileExists == st.myFileExists;
return ((MyValidityState)otherState).myTimestamps.equals(myTimestamps);
}
@Override
public void save(DataOutput out) throws IOException {
out.writeLong(myTimestamp);
out.writeInt(myTimestamps.size());
for (Map.Entry<String, Long> entry : myTimestamps.entrySet()) {
out.writeUTF(entry.getKey());
out.writeLong(entry.getValue());
}
}
}
}
@@ -152,12 +152,14 @@ public class AndroidResourcesPackagingCompiler implements ClassPostProcessingCom
? item.myOutputPath + RELEASE_SUFFIX
: item.myOutputPath;
Map<CompilerMessageCategory, List<String>> messages = AndroidApt.packageResources(item.myAndroidTarget,
item.myPlatformToolsRevision,
preprocessedManifestFile.getPath(),
item.myResourceDirPaths,
item.myAssetsDirPath,
outputPath, null, !releasePackage, 0);
Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidApt.packageResources(item.myAndroidTarget,
item.myPlatformToolsRevision,
preprocessedManifestFile.getPath(),
item.myResourceDirPaths,
item.myAssetsDirPath,
outputPath, null, !releasePackage, 0));
AndroidCompileUtil.addMessages(context, messages, presentableFilesMap);
}
catch (final IOException e) {
@@ -33,11 +33,11 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.text.DateFormatUtil;
import org.jetbrains.android.compiler.AndroidCompileUtil;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -141,7 +141,7 @@ public class AndroidApkBuilder {
map.putAll(map2);
if (withAlignment && map.get(ERROR).size() == 0) {
map2 = ExecutionUtil.execute(zipAlignPath, "-f", "4", unalignedApk, finalApk);
map2 = AndroidCompileUtil.execute(zipAlignPath, "-f", "4", unalignedApk, finalApk);
map.putAll(map2);
}
return map;
@@ -37,7 +37,6 @@ import com.intellij.facet.FacetTypeRegistry;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.GeneratingCompiler;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
@@ -65,18 +64,16 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import com.intellij.util.xml.ConvertContext;
import com.intellij.util.xml.DomElement;
import org.jetbrains.android.compiler.AndroidAptCompiler;
import org.jetbrains.android.compiler.AndroidAutogeneratorMode;
import org.jetbrains.android.compiler.AndroidCompileUtil;
import org.jetbrains.android.compiler.AndroidIdlCompiler;
import org.jetbrains.android.compiler.AndroidRenderscriptCompiler;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.importDependencies.ImportDependenciesUtil;
import org.jetbrains.android.resourceManagers.LocalResourceManager;
@@ -112,27 +109,96 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
private final Map<String, Map<String, PsiClass>> myClassMaps = new HashMap<String, Map<String, PsiClass>>();
private final Object myClassMapLock = new Object();
private final Map<Class<?>, MergingUpdateQueue> mySourcesAutogeneratingQueueMap = new HashMap<Class<?>, MergingUpdateQueue>();
private final Set<AndroidAutogeneratorMode> myDirtyModes = EnumSet.noneOf(AndroidAutogeneratorMode.class);
private final Map<AndroidAutogeneratorMode, Set<String>> myAutogeneratedFiles = new HashMap<AndroidAutogeneratorMode, Set<String>>();
private volatile boolean myAutogenerationEnabled = false;
public AndroidFacet(@NotNull Module module, String name, @NotNull AndroidFacetConfiguration configuration) {
super(getFacetType(), module, name, configuration, null);
configuration.setFacet(this);
mySourcesAutogeneratingQueueMap.put(AndroidAptCompiler.class, createSourceGeneratingQueue("AndroidAptAutogeneratingQueue"));
mySourcesAutogeneratingQueueMap.put(AndroidIdlCompiler.class, createSourceGeneratingQueue("AndroidIdlAutogeneratingQueue"));
mySourcesAutogeneratingQueueMap
.put(AndroidRenderscriptCompiler.class, createSourceGeneratingQueue("AndroidRenderscriptAutogeneratingQueue"));
for (AndroidAutogeneratorMode mode : AndroidAutogeneratorMode.values()) {
createAlarm(mode);
}
}
private MergingUpdateQueue createSourceGeneratingQueue(@NotNull String name) {
return new MergingUpdateQueue(name, 1000, false, null, this, null, false);
private Alarm createAlarm(@NotNull final AndroidAutogeneratorMode mode) {
final Alarm alarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, this);
alarm.addRequest(new Runnable() {
@Override
public void run() {
boolean regenerate;
synchronized (myDirtyModes) {
regenerate = myDirtyModes.contains(mode);
}
regenerate = regenerate || isGeneratedFileRemoved(mode);
if (myAutogenerationEnabled && regenerate) {
if (AndroidCompileUtil.doGenerate(getModule(), mode)) {
synchronized (myDirtyModes) {
myDirtyModes.remove(mode);
}
}
}
if (!alarm.isDisposed()) {
alarm.addRequest(this, 2000);
}
}
}, 2000);
return alarm;
}
private boolean isGeneratedFileRemoved(@NotNull AndroidAutogeneratorMode mode) {
synchronized (myAutogeneratedFiles) {
final Set<String> filePaths = myAutogeneratedFiles.get(mode);
if (filePaths != null) {
for (String path : filePaths) {
final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(path);
if (file == null) {
return true;
}
}
}
}
return false;
}
public void clearAutogeneratedFiles(@NotNull AndroidAutogeneratorMode mode) {
synchronized (myAutogeneratedFiles) {
final Set<String> set = myAutogeneratedFiles.get(mode);
if (set != null) {
set.clear();
}
}
}
public void markFileAutogenerated(@NotNull AndroidAutogeneratorMode mode, @NotNull VirtualFile file) {
synchronized (myAutogeneratedFiles) {
Set<String> set = myAutogeneratedFiles.get(mode);
if (set == null) {
set = new HashSet<String>();
myAutogeneratedFiles.put(mode, set);
}
set.add(file.getPath());
}
}
@NotNull
public Set<String> getAutogeneratedFiles(@NotNull AndroidAutogeneratorMode mode) {
synchronized (myAutogeneratedFiles) {
final Set<String> set = myAutogeneratedFiles.get(mode);
return set != null ? new HashSet<String>(set) : Collections.<String>emptySet();
}
}
private void activateSourceAutogenerating() {
for (MergingUpdateQueue queue : mySourcesAutogeneratingQueueMap.values()) {
queue.activate();
}
myAutogenerationEnabled = true;
}
@Nullable
@@ -385,12 +451,12 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
myListener.setResourceSet(resourceSet);
if (getConfiguration().REGENERATE_R_JAVA && AndroidAptCompiler.isToCompileModule(module, getConfiguration())) {
AndroidCompileUtil.generate(module, new AndroidAptCompiler());
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AAPT);
}
if (getConfiguration().REGENERATE_JAVA_BY_AIDL) {
AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project));
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AIDL);
}
AndroidCompileUtil.generate(module, new AndroidRenderscriptCompiler());
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.RENDERSCRIPT);
activateSourceAutogenerating();
}
@@ -774,19 +840,9 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
return moduleDirPath != null ? FileUtil.toSystemDependentName(moduleDirPath + path) : null;
}
public void scheduleSourceRegenerating(@NotNull final GeneratingCompiler compiler) {
final MergingUpdateQueue queue = mySourcesAutogeneratingQueueMap.get(compiler.getClass());
if (queue == null) {
LOG.error("Autogenerating is not supported for compiler " + compiler.getClass().getCanonicalName());
}
else {
queue.queue(new Update(this) {
@Override
public void run() {
AndroidCompileUtil.doGenerate(getModule(), compiler);
}
});
public void scheduleSourceRegenerating(@NotNull final AndroidAutogeneratorMode mode) {
synchronized (myDirtyModes) {
myDirtyModes.add(mode);
}
}
}
@@ -37,8 +37,8 @@ import com.intellij.ui.components.JBLabel;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.android.compiler.AndroidAptCompiler;
import org.jetbrains.android.compiler.AndroidAutogeneratorMode;
import org.jetbrains.android.compiler.AndroidCompileUtil;
import org.jetbrains.android.compiler.AndroidIdlCompiler;
import org.jetbrains.android.maven.AndroidMavenProvider;
import org.jetbrains.android.maven.AndroidMavenUtil;
import org.jetbrains.android.util.AndroidBundle;
@@ -437,10 +437,10 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
final Project project = module.getProject();
if (runApt) {
AndroidCompileUtil.generate(module, new AndroidAptCompiler(), true);
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AAPT, true);
}
if (runIdl) {
AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project));
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AIDL);
}
}
}
@@ -18,7 +18,6 @@ package org.jetbrains.android.facet;
import com.android.resources.ResourceFolderType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.GeneratingCompiler;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.DumbService;
@@ -28,7 +27,9 @@ import com.intellij.openapi.vfs.*;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.android.compiler.*;
import org.jetbrains.android.compiler.AndroidAptCompiler;
import org.jetbrains.android.compiler.AndroidAutogeneratorMode;
import org.jetbrains.android.compiler.AndroidCompileUtil;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.fileTypes.AndroidIdlFileType;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
@@ -111,9 +112,6 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
private void fileChanged(@NotNull final VirtualFileEvent e) {
VirtualFile file = e.getFile();
if (!file.isValid()) {
return;
}
VirtualFile parent = e.getParent();
VirtualFile gp = parent != null ? parent.getParent() : null;
@@ -146,18 +144,19 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
return;
}
final GeneratingCompiler compilerToRun = ApplicationManager.getApplication().runReadAction(new Computable<GeneratingCompiler>() {
@Nullable
public GeneratingCompiler compute() {
return computeCompilerToRunAndInvalidateLocalAttributesMap();
}
});
final AndroidAutogeneratorMode autogenerationMode =
ApplicationManager.getApplication().runReadAction(new Computable<AndroidAutogeneratorMode>() {
@Nullable
public AndroidAutogeneratorMode compute() {
return computeCompilerToRunAndInvalidateLocalAttributesMap();
}
});
if (compilerToRun == null) {
if (autogenerationMode == null) {
return;
}
if (compilerToRun instanceof AndroidAptCompiler &&
if (autogenerationMode == AndroidAutogeneratorMode.AAPT &&
AndroidRootUtil.getManifestFile(myFacet.getModule()) != myEvent.getFile()) {
final HashSet<ResourceEntry> resourceSet = new HashSet<ResourceEntry>();
@@ -173,11 +172,11 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
myResourceSet = resourceSet;
}
}
AndroidCompileUtil.generate(myFacet.getModule(), compilerToRun, true);
AndroidCompileUtil.generate(myFacet.getModule(), autogenerationMode, true);
}
@Nullable
private GeneratingCompiler computeCompilerToRunAndInvalidateLocalAttributesMap() {
private AndroidAutogeneratorMode computeCompilerToRunAndInvalidateLocalAttributesMap() {
if (myFacet.isDisposed()) {
return null;
}
@@ -219,20 +218,20 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
AndroidCompileUtil.removeDuplicatingClasses(myModule, myCachedPackage, AndroidUtils.R_CLASS_NAME, null, aptGenDirPath);
}
myCachedPackage = aPackage;
return new AndroidAptCompiler();
return AndroidAutogeneratorMode.AAPT;
}
if (myFacet.getConfiguration().REGENERATE_JAVA_BY_AIDL && file.getFileType() == AndroidIdlFileType.ourFileType) {
VirtualFile sourceRoot = findSourceRoot(myModule, file);
if (sourceRoot != null && AndroidRootUtil.getAidlGenDir(module, myFacet) != sourceRoot) {
return new AndroidIdlCompiler(project);
return AndroidAutogeneratorMode.AIDL;
}
}
if (file.getFileType() == AndroidRenderscriptFileType.INSTANCE) {
final VirtualFile sourceRoot = findSourceRoot(myModule, file);
if (sourceRoot != null && AndroidRootUtil.getRenderscriptGenDir(myModule) != sourceRoot) {
return new AndroidRenderscriptCompiler();
return AndroidAutogeneratorMode.RENDERSCRIPT;
}
}
return null;
@@ -99,7 +99,7 @@ public class AndroidResourceUtil {
collectDirsForPackage(module, project, null, dirs, new HashSet<Module>(), onlyInOwnPackages);
List<PsiJavaFile> rJavaFiles = new ArrayList<PsiJavaFile>();
for (PsiDirectory dir : dirs) {
VirtualFile file = dir.getVirtualFile().findChild(AndroidUtils.R_JAVA_FILENAME);
VirtualFile file = dir.getVirtualFile().findChild(AndroidCommonUtils.R_JAVA_FILENAME);
if (file != null) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
if (psiFile instanceof PsiJavaFile) {
@@ -113,7 +113,6 @@ public class AndroidUtils {
public static final Icon RESTART_LOGCAT_ICON = IconLoader.getIcon("/icons/restartLogcat.png");
public static final String NAMESPACE_KEY = "android";
public static final String SYSTEM_RESOURCE_PACKAGE = "android";
public static final String R_JAVA_FILENAME = "R.java";
public static final String ANDROID_PACKAGE = "android";
public static final String VIEW_CLASS_NAME = ANDROID_PACKAGE + ".view.View";
public static final String APPLICATION_CLASS_NAME = "android.app.Application";
@@ -148,7 +147,6 @@ public class AndroidUtils {
public static final String PROVIDER_CLASS_NAME = "android.content.ContentProvider";
@NonNls public static final String DEFAULT_PROPERTIES_FILE_NAME = "default.properties";
@NonNls public static final String PNG_EXTENSION = "png";
@NonNls public static final Object MANIFEST_JAVA_FILE_NAME = "Manifest.java";
private AndroidUtils() {
}
@@ -259,7 +257,7 @@ public class AndroidUtils {
}
public static boolean isRClassFile(@NotNull AndroidFacet facet, @NotNull PsiFile file) {
if (file.getName().equals(R_JAVA_FILENAME) && file instanceof PsiJavaFile) {
if (file.getName().equals(AndroidCommonUtils.R_JAVA_FILENAME) && file instanceof PsiJavaFile) {
PsiJavaFile javaFile = (PsiJavaFile)file;
Manifest manifest = facet.getManifest();
if (manifest == null) return false;
@@ -961,20 +959,6 @@ public class AndroidUtils {
return xmlFiles;
}
public static String command2string(@NotNull Collection<String> command) {
final StringBuilder builder = new StringBuilder();
for (Iterator<String> it = command.iterator(); it.hasNext(); ) {
String s = it.next();
builder.append('[');
builder.append(s);
builder.append(']');
if (it.hasNext()) {
builder.append(' ');
}
}
return builder.toString();
}
@Nullable
public static String getProjectPropertyValue(Module module, String propertyName) {
final String result = getPropertyValue(module, SdkConstants.FN_PROJECT_PROPERTIES, propertyName);
@@ -1,134 +0,0 @@
/*
* Copyright 2000-2010 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.android.util;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Abstract external tool for compiler.
*
* @author Alexey Efimov
*/
public final class ExecutionUtil {
private static final String IGNORING = "ignoring";
private static final String SKIPPING = "skipping";
private ExecutionUtil() {
}
// can't be invoked from dispatch thread
@NotNull
public static Map<CompilerMessageCategory, List<String>> execute(String... argv) throws IOException {
assert !ApplicationManager.getApplication().isDispatchThread();
ProcessBuilder builder = new ProcessBuilder(argv);
ProcessResult result = readProcessOutput(builder.start());
Map<CompilerMessageCategory, List<String>> messages = result.getMessages();
int code = result.getExitCode();
List<String> errMessages = messages.get(CompilerMessageCategory.ERROR);
if (code != 0 && errMessages.isEmpty()) {
throw new IOException(AndroidBundle.message("command.0.execution.failed.with.exit.code.1", concat(argv), code));
}
else {
if (code == 0) {
messages.get(CompilerMessageCategory.INFORMATION).addAll(errMessages);
errMessages.clear();
}
return messages;
}
}
private static String concat(String... strs) {
StringBuilder builder = new StringBuilder();
for (int i = 0, n = strs.length; i < n; i++) {
builder.append(strs[i]);
if (i < n - 1) {
builder.append(' ');
}
}
return builder.toString();
}
@NotNull
private static ProcessResult readProcessOutput(Process process) throws IOException {
assert !ApplicationManager.getApplication().isDispatchThread();
OSProcessHandler handler = new OSProcessHandler(process, "");
final List<String> information = new ArrayList<String>();
final List<String> error = new ArrayList<String>();
handler.addProcessListener(new ProcessAdapter() {
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
String output = event.getText();
if (StringUtil.isEmptyOrSpaces(output)) {
return;
}
String[] lines = output.split("[\\n\\r]+");
for (String line : lines) {
String l = line.toLowerCase();
if (outputType == ProcessOutputTypes.STDOUT) {
information.add(line);
}
else if (outputType == ProcessOutputTypes.STDERR) {
if (l.contains(IGNORING) || l.contains(SKIPPING)) {
information.add(line);
}
else {
error.add(line);
}
}
}
}
});
handler.startNotify();
handler.waitFor();
int exitCode = handler.getProcess().exitValue();
return new ProcessResult(information, error, exitCode);
}
private static final class ProcessResult {
private final int myExitCode;
private final Map<CompilerMessageCategory, List<String>> myMessages;
public ProcessResult(List<String> information, List<String> error, int exitCode) {
myExitCode = exitCode;
myMessages = new HashMap<CompilerMessageCategory, List<String>>(2);
myMessages.put(CompilerMessageCategory.INFORMATION, information);
myMessages.put(CompilerMessageCategory.ERROR, error);
}
public Map<CompilerMessageCategory, List<String>> getMessages() {
return myMessages;
}
public int getExitCode() {
return myExitCode;
}
}
}
@@ -41,6 +41,7 @@ public interface EclipseXml {
@NonNls String JRE_CONTAINER_SPECIFIC = JRE_CONTAINER + "/" + "org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType";
@NonNls String USER_LIBRARY = "org.eclipse.jdt.USER_LIBRARY";
@NonNls String JUNIT_CONTAINER = "org.eclipse.jdt.junit.JUNIT_CONTAINER";
@NonNls String GROOVY_DSL_CONTAINER = "GROOVY_DSL_SUPPORT";
@NonNls String JUNIT3 = JUNIT_CONTAINER + "/" + "3.8.1";
@NonNls String JUNIT4 = JUNIT_CONTAINER + "/" + "4";
@NonNls String ECLIPSE_PLATFORM = "org.eclipse.pde.core.requiredPlugins";
@@ -148,6 +148,7 @@ public class EclipseClasspathStorageProvider implements ClasspathStorageProvider
LocalFileSystem.getInstance().refreshAndFindFileByIoFile(target);
}
final CachedXmlDocumentSet fileCache = getFileCache(module);
DotProjectFileHelper.saveDotProjectFile(module, fileCache.getParent(EclipseXml.PROJECT_FILE));
fileCache.delete(oldEmlName);
fileCache.register(newName + EclipseXml.IDEA_SETTINGS_POSTFIX, ClasspathStorage.getModuleDir(module));
fileCache.load(newName + EclipseXml.IDEA_SETTINGS_POSTFIX);
@@ -62,6 +62,7 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
private int myExpectedModuleSourcePlace;
private Map<String, Integer> mySrcPlace = new LinkedHashMap<String, Integer>();
private String myInvalidJdk;
private boolean myGroovyDslSupport = false;
public EclipseModuleManager(Module module) {
myModule = module;
@@ -75,6 +76,14 @@ public class EclipseModuleManager implements PersistentStateComponent<Element>{
return myInvalidJdk;
}
public void setGroovyDslSupport() {
myGroovyDslSupport = true;
}
public boolean isGroovyDslSupport() {
return myGroovyDslSupport;
}
public static EclipseModuleManager getInstance(Module module) {
return ModuleServiceManager.getService(module, EclipseModuleManager.class);
}
@@ -272,7 +272,12 @@ public class EclipseClasspathReader {
final Library.ModifiableModel modifiableModel = library.getModifiableModel();
modifiableModel.addRoot(getJunitClsUrl(junitName.contains("4")), OrderRootType.CLASSES);
modifiableModel.commit();
} else {
}
else if (path.equals(EclipseXml.GROOVY_DSL_CONTAINER)) {
eclipseModuleManager.setGroovyDslSupport();
eclipseModuleManager.registerSrcPlace(EclipseXml.GROOVY_DSL_CONTAINER, idx);
}
else {
eclipseModuleManager.registerUnknownCons(path);
addNamedLibrary(rootModel, new ArrayList<String>(), exported, path, LibraryTablesRegistrar.APPLICATION_LEVEL);
}
@@ -64,7 +64,8 @@ public class EclipseClasspathWriter {
@NonNls String outputPath = "bin";
final String compilerOutputUrl = myModel.getModuleExtension(CompilerModuleExtension.class).getCompilerOutputUrl();
final String linkedPath = EclipseModuleManager.getInstance(myModel.getModule()).getEclipseLinkedVarPath(compilerOutputUrl);
final EclipseModuleManager eclipseModuleManager = EclipseModuleManager.getInstance(myModel.getModule());
final String linkedPath = eclipseModuleManager.getEclipseLinkedVarPath(compilerOutputUrl);
if (linkedPath != null) {
outputPath = linkedPath;
} else {
@@ -77,6 +78,10 @@ public class EclipseClasspathWriter {
outputPath = EPathUtil.collapse2EclipsePath(compilerOutputUrl, myModel);
}
}
if (eclipseModuleManager.isGroovyDslSupport()) {
final Integer place = eclipseModuleManager.getSrcPlace(EclipseXml.GROOVY_DSL_CONTAINER);
addOrderEntry(EclipseXml.CON_KIND, EclipseXml.GROOVY_DSL_CONTAINER, classpathElement, place != null ? place.intValue() : -1);
}
final Element orderEntry = addOrderEntry(EclipseXml.OUTPUT_KIND, outputPath, classpathElement);
setAttributeIfAbsent(orderEntry, EclipseXml.PATH_ATTR, EclipseXml.BIN_DIR);
}
@@ -77,6 +77,8 @@ gradle.action.refresh.project.text=Refresh gradle project
gradle.action.refresh.project.description=Allows to force linked gradle project refresh
gradle.action.open.script.text=Open linked gradle project
gradle.action.open.script.description=Allows to open project file of the linked gradle project at the editor
gradle.action.import.entity.text=Import
gradle.action.import.entity.description=Import target gradle entity
gradle.settings.color.text.sample.conflict.node.name=node-with-conflicting-setup
gradle.settings.color.text.sample.node.sync.name=node-with-same-setup
+16 -4
View File
@@ -34,17 +34,25 @@
<colorAndFontPanelFactory implementation="org.jetbrains.plugins.gradle.config.GradleColorAndFontPanelFactory"/>
<colorAndFontDescriptorProvider implementation="org.jetbrains.plugins.gradle.config.GradleColorAndFontDescriptorsProvider"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.util.GradleLibraryManager"/>
<!--Structure diff calculators-->
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator"
serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleModuleStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleLibraryStructureChangesCalculator"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleLibraryDependencyStructureChangesCalculator"/>
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.PlatformFacade"
serviceImplementation="org.jetbrains.plugins.gradle.diff.PlatformFacadeImpl"/>
<!--Import services-->
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.importing.GradleModuleImporter"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.importing.GradleContentRootImporter"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.importing.GradleModuleDependencyImporter"/>
<!--Generic application services-->
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.util.GradleLibraryManager"/>
<applicationService serviceInterface="org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager"
serviceImplementation="org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl"/>
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.PlatformFacade"
serviceImplementation="org.jetbrains.plugins.gradle.diff.PlatformFacadeImpl"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.config.GradleSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.config.GradleProjectState"/>
@@ -72,10 +80,14 @@
<action id="Gradle.LinkToProject" class="org.jetbrains.plugins.gradle.action.GradleLinkToProjectAction" icon="/general/add.png"/>
<action id="Gradle.RefreshProject" class="org.jetbrains.plugins.gradle.action.GradleRefreshProjectAction" icon="/actions/sync.png"/>
<action id="Gradle.OpenScript" class="org.jetbrains.plugins.gradle.action.GradleOpenScriptAction" icon="/icons/gradle.png"/>
<action id="Gradle.ImportEntity" class="org.jetbrains.plugins.gradle.action.GradleImportEntityAction"/>
<group id="Gradle.ChangeActionsToolbar">
<reference id="Gradle.RefreshProject"/>
<reference id="Gradle.OpenScript"/>
</group>
<group id="Gradle.SyncTreeGroup">
<reference id="Gradle.ImportEntity"/>
</group>
</actions>
</idea-plugin>
@@ -0,0 +1,131 @@
package org.jetbrains.plugins.gradle.action;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.importing.GradleModuleDependencyImporter;
import org.jetbrains.plugins.gradle.importing.GradleModuleImporter;
import org.jetbrains.plugins.gradle.model.GradleLibraryDependency;
import org.jetbrains.plugins.gradle.model.GradleLibraryDependencyId;
import org.jetbrains.plugins.gradle.model.GradleModule;
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper;
import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Imports target {@link GradleTextAttributes#GRADLE_LOCAL_CHANGE 'gradle local'} entity to the current intellij project.
* <p/>
* Not thread-safe.
*
* @author Denis Zhdanov
* @since 2/7/12 10:32 AM
*/
public class GradleImportEntityAction extends AnAction {
private static final Logger LOG = Logger.getInstance("#" + GradleImportEntityAction.class.getName());
public GradleImportEntityAction() {
getTemplatePresentation().setText(GradleBundle.message("gradle.action.import.entity.text"));
getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.import.entity.description"));
}
@Override
public void update(AnActionEvent e) {
final Collection<GradleProjectStructureNode<?>> nodes = getInterestedNodes(e.getDataContext());
e.getPresentation().setEnabled(!nodes.isEmpty());
}
@Override
public void actionPerformed(AnActionEvent e) {
final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
if (project == null) {
LOG.warn("Can't import gradle-local entities. Reason: target intellij project is undefined");
return;
}
final Collection<GradleProjectStructureNode<?>> nodes = getInterestedNodes(e.getDataContext());
// We need to import not only the selected nodes but their gradle-local parents as well.
List<GradleProjectStructureNode<?>> nodesToImport = new ArrayList<GradleProjectStructureNode<?>>();
for (GradleProjectStructureNode<?> node : nodes) {
collectHierarchyToImport(node, nodesToImport);
}
GradleProjectStructureHelper projectStructureHelper = project.getComponent(GradleProjectStructureHelper.class);
GradleModuleImporter moduleImporter = ServiceManager.getService(GradleModuleImporter.class);
GradleModuleDependencyImporter dependencyImporter = ServiceManager.getService(GradleModuleDependencyImporter.class);
for (GradleProjectStructureNode<?> node : nodesToImport) {
switch (node.getType()) {
case MODULE:
final GradleModule gradleModule = projectStructureHelper.findGradleModuleByName(node.getDescriptor().getName());
if (gradleModule != null) {
moduleImporter.importModule(gradleModule, project);
}
break;
case LIBRARY_DEPENDENCY:
final Object element = node.getDescriptor().getElement();
if (!(element instanceof GradleLibraryDependencyId)) {
break;
}
GradleLibraryDependencyId id = (GradleLibraryDependencyId)element;
final GradleLibraryDependency dependency = projectStructureHelper.findLibraryDependency(id);
final Module intellijModule = projectStructureHelper.findIntellijModuleByName(id.getModuleName());
if (dependency != null && intellijModule != null) {
dependencyImporter.importDependency(dependency, intellijModule);
}
break;
default: // Do nothing
}
}
}
/**
* When particular gradle-local node is asked to be imported we need to import its gradle-local parent hierarchy as well.
* <p/>
* This method allows to collect all parent nodes of the given nodes that should be imported as well.
* <p/>
* <b>Note:</b> those nodes are added to the given collection starting from the topmost one.
*
* @param node target node
* @param storage target nodes storage
*/
private static void collectHierarchyToImport(@Nullable GradleProjectStructureNode<?> node,
@NotNull Collection<GradleProjectStructureNode<?>> storage)
{
if (node == null || node.getDescriptor().getAttributes() != GradleTextAttributes.GRADLE_LOCAL_CHANGE) {
return;
}
collectHierarchyToImport(node.getParent(), storage);
storage.add(node);
}
@NotNull
private static Collection<GradleProjectStructureNode<?>> getInterestedNodes(@NotNull DataContext context) {
final Collection<GradleProjectStructureNode<?>> selectedNodes = GradleDataKeys.SYNC_TREE_NODE.getData(context);
if (selectedNodes == null) {
return Collections.emptyList();
}
List<GradleProjectStructureNode<?>> result = new ArrayList<GradleProjectStructureNode<?>>();
for (GradleProjectStructureNode<?> node : selectedNodes) {
if (node.getDescriptor().getAttributes() == GradleTextAttributes.GRADLE_LOCAL_CHANGE) {
result.add(node);
}
}
return result;
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.diff;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
@@ -28,6 +29,9 @@ import java.util.Collection;
*/
public interface PlatformFacade {
@NotNull
LibraryTable getProjectLibraryTable(@NotNull Project project);
@NotNull
LanguageLevel getLanguageLevel(@NotNull Project project);
@@ -8,6 +8,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -24,6 +26,12 @@ import java.util.Collection;
*/
public class PlatformFacadeImpl implements PlatformFacade {
@NotNull
@Override
public LibraryTable getProjectLibraryTable(@NotNull Project project) {
return ProjectLibraryTable.getInstance(project);
}
@NotNull
@Override
public LanguageLevel getLanguageLevel(@NotNull Project project) {
@@ -0,0 +1,16 @@
package org.jetbrains.plugins.gradle.importing;
import com.intellij.openapi.module.Module;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.GradleContentRoot;
/**
* @author Denis Zhdanov
* @since 2/7/12 3:20 PM
*/
public class GradleContentRootImporter {
public void importContentRoots(@NotNull Iterable<GradleContentRoot> contentRoots, @NotNull Module module) {
// TODO den implement
}
}
@@ -0,0 +1,152 @@
package org.jetbrains.plugins.gradle.importing;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
import org.jetbrains.plugins.gradle.model.*;
import org.jetbrains.plugins.gradle.util.GradleLog;
import java.io.File;
import java.util.*;
/**
* @author Denis Zhdanov
* @since 2/7/12 3:23 PM
*/
public class GradleModuleDependencyImporter {
private static final Map<LibraryPathType, OrderRootType> LIBRARY_ROOT_MAPPINGS
= new EnumMap<LibraryPathType, OrderRootType>(LibraryPathType.class);
static {
LIBRARY_ROOT_MAPPINGS.put(LibraryPathType.BINARY, OrderRootType.CLASSES);
LIBRARY_ROOT_MAPPINGS.put(LibraryPathType.SOURCE, OrderRootType.SOURCES);
LIBRARY_ROOT_MAPPINGS.put(LibraryPathType.DOC, JavadocOrderRootType.getInstance());
assert LibraryPathType.values().length == LIBRARY_ROOT_MAPPINGS.size();
}
@NotNull private final PlatformFacade myPlatformFacade;
public GradleModuleDependencyImporter(@NotNull PlatformFacade platformFacade) {
myPlatformFacade = platformFacade;
}
public void importDependency(@NotNull GradleDependency dependency, @NotNull Module module) {
importDependencies(Collections.singleton(dependency), module);
}
public void importDependencies(@NotNull Iterable<GradleDependency> dependencies, @NotNull Module module) {
final List<GradleModuleDependency> moduleDependencies = new ArrayList<GradleModuleDependency>();
final List<GradleLibraryDependency> libraryDependencies = new ArrayList<GradleLibraryDependency>();
GradleEntityVisitor visitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
moduleDependencies.add(dependency);
}
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
libraryDependencies.add(dependency);
}
};
for (GradleDependency dependency : dependencies) {
dependency.invite(visitor);
}
importLibraryDependencies(libraryDependencies, module);
importModuleDependencies(moduleDependencies, module);
}
public void importModuleDependencies(@NotNull Iterable<GradleModuleDependency> dependencies, @NotNull Module module) {
// TODO den implement
}
public void importLibraryDependencies(@NotNull final Iterable<GradleLibraryDependency> dependencies, @NotNull final Module module) {
// TODO den make non-EDT agnostic
final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject());
final Map<GradleLibrary, Library> gradle2intellij = new HashMap<GradleLibrary, Library>();
final Set<GradleLibrary> librariesToCreate = new HashSet<GradleLibrary>();
for (final GradleLibraryDependency dependency : dependencies) {
// Try to find existing library in project libraries.
Library library = libraryTable.getLibraryByName(dependency.getName());
if (library == null) {
librariesToCreate.add(dependency.getTarget());
}
else {
gradle2intellij.put(dependency.getTarget(), library);
}
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
// Create all necessary libraries.
if (!librariesToCreate.isEmpty()) {
final LibraryTable.ModifiableModel projectLibraryModel = libraryTable.getModifiableModel();
try {
for (GradleLibrary library : librariesToCreate) {
final Library intellijLibrary = projectLibraryModel.createLibrary(library.getName());
gradle2intellij.put(library, intellijLibrary);
final Library.ModifiableModel libraryModel = intellijLibrary.getModifiableModel();
try {
registerPaths(library, libraryModel);
}
finally {
libraryModel.commit();
}
}
}
finally {
projectLibraryModel.commit();
}
}
// Register library dependencies.
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
try {
for (GradleLibraryDependency dependency : dependencies) {
LibraryOrderEntry orderEntry = moduleRootModel.addLibraryEntry(gradle2intellij.get(dependency.getTarget()));
orderEntry.setExported(dependency.isExported());
orderEntry.setScope(dependency.getScope());
}
}
finally {
moduleRootModel.commit();
}
// TODO den refresh gradle project tree
}
});
}
private static void registerPaths(@NotNull GradleLibrary gradleLibrary, @NotNull Library.ModifiableModel model) {
for (LibraryPathType pathType : LibraryPathType.values()) {
for (String path : gradleLibrary.getPaths(pathType)) {
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(new File(path));
if (virtualFile == null) {
GradleLog.LOG.warn(String.format("Can't find %s of the library '%s' at path '%s'", pathType, gradleLibrary.getName(), path));
continue;
}
if (virtualFile.isDirectory()) {
model.addRoot(virtualFile, LIBRARY_ROOT_MAPPINGS.get(pathType));
}
else {
VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile);
if (jarRoot == null) {
GradleLog.LOG.warn(String.format(
"Can't parse contents of the jar file at path '%s' for the library '%s''", path, gradleLibrary.getName()
));
continue;
}
model.addRoot(jarRoot, LIBRARY_ROOT_MAPPINGS.get(pathType));
}
}
}
}
}
@@ -0,0 +1,125 @@
package org.jetbrains.plugins.gradle.importing;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
import com.intellij.util.Alarm;
import com.intellij.util.containers.hash.HashMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.GradleModule;
import org.jetbrains.plugins.gradle.util.GradleLog;
import java.io.File;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Encapsulates functionality of importing gradle module to the intellij project.
*
* @author Denis Zhdanov
* @since 2/7/12 2:49 PM
*/
public class GradleModuleImporter {
/**
* We can't modify project modules (add/remove) until it's initialised, so, we delay that activity. Current constant
* holds number of milliseconds to wait between 'after project initialisation' processing attempts.
*/
private static final int PROJECT_INITIALISATION_DELAY_MS = (int)TimeUnit.SECONDS.toMillis(1);
private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
@NotNull private final GradleContentRootImporter myContentRootImporter;
@NotNull private final GradleModuleDependencyImporter myDependencyImporter;
public GradleModuleImporter(@NotNull GradleContentRootImporter contentRootImporter,
@NotNull GradleModuleDependencyImporter dependencyImporter)
{
myContentRootImporter = contentRootImporter;
myDependencyImporter = dependencyImporter;
}
public void importModule(@NotNull GradleModule module, @NotNull Project project) {
importModules(Collections.singleton(module), project, false);
}
public void importModules(@NotNull final Iterable<GradleModule> modules, @NotNull final Project project, final boolean recursive) {
if (!project.isInitialized()) {
myAlarm.addRequest(new ImportModulesTask(project, modules, recursive), PROJECT_INITIALISATION_DELAY_MS);
return;
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
removeExistingModulesConfigs(modules);
Application application = ApplicationManager.getApplication();
final Map<GradleModule, Module> moduleMappings = new HashMap<GradleModule, Module>();
application.runWriteAction(new Runnable() {
@Override
public void run() {
final ModuleManager moduleManager = ModuleManager.getInstance(project);
for (GradleModule module : modules) {
final Module created = moduleManager.newModule(module.getModuleFilePath(), StdModuleTypes.JAVA);
moduleMappings.put(module, created);
}
}
});
if (!recursive) {
return;
}
for (GradleModule gradleModule : modules) {
final Module intellijModule = moduleMappings.get(gradleModule);
myContentRootImporter.importContentRoots(gradleModule.getContentRoots(), intellijModule);
myDependencyImporter.importDependencies(gradleModule.getDependencies(), intellijModule);
}
}
});
}
private static void removeExistingModulesConfigs(@NotNull Iterable<GradleModule> modules) {
for (GradleModule module : modules) {
// Remove existing '*.iml' file if necessary.
final String moduleFilePath = module.getModuleFilePath();
File file = new File(moduleFilePath);
if (file.isFile()) {
boolean success = file.delete();
if (!success) {
GradleLog.LOG.warn("Can't remove existing module file at '" + moduleFilePath + "'");
}
}
}
}
private class ImportModulesTask implements Runnable {
private final Project myProject;
private final Iterable<GradleModule> myModules;
private final boolean myRecursive;
ImportModulesTask(@NotNull Project project, @NotNull Iterable<GradleModule> modules, boolean recursive) {
myProject = project;
myModules = modules;
myRecursive = recursive;
}
@Override
public void run() {
myAlarm.cancelAllRequests();
if (!myProject.isInitialized()) {
myAlarm.addRequest(
new ImportModulesTask(myProject, myModules, myRecursive),
PROJECT_INITIALISATION_DELAY_MS
);
return;
}
importModules(myModules, myProject, myRecursive);
}
}
}
@@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
* @author Denis Zhdanov
* @since 8/26/11 10:01 AM
*/
// TODO den remove
public class GradleModulesImporter {
private static final Map<LibraryPathType, OrderRootType> LIBRARY_ROOT_MAPPINGS
@@ -260,7 +260,7 @@ public class GradleAdjustImportSettingsStep extends AbstractImportFromGradleWiza
// We build tree node, its settings control and map them altogether. The only trick here is that nodes can reuse the same
// settings control (e.g. more than one node may have the same library as a dependency, so, library dependency node for
// every control will use the same settings control).
GradleProjectStructureNode<T> result = new GradleProjectStructureNode<T>(myFactory.buildDescriptor(entity));
GradleProjectStructureNode<T> result = new GradleProjectStructureNode<T>(myFactory.buildDescriptor(entity), GradleEntityType.SYNTHETIC);
Pair<String, Collection<GradleProjectStructureNode>> pair = processed.get(entity);
if (pair == null) {
String cardName = String.valueOf(counter);
@@ -138,7 +138,7 @@ public class GradleProjectStructureFactory {
return;
}
for (GradleProjectStructureNode node : treeNodes) {
node.getDescriptor().setText(evt.getNewValue().toString());
node.getDescriptor().setName(evt.getNewValue().toString());
model.nodeChanged(node);
}
}
@@ -15,6 +15,9 @@ public interface GradleDependency extends GradleEntity {
@NotNull
DependencyScope getScope();
@NotNull
GradleModule getOwnerModule();
@NotNull
GradleDependency clone(@NotNull GradleEntityCloneContext context);
@@ -0,0 +1,9 @@
package org.jetbrains.plugins.gradle.model;
/**
* @author Denis Zhdanov
* @since 2/7/12 11:18 AM
*/
public enum GradleEntityType {
PROJECT, MODULE, LIBRARY_DEPENDENCY, SYNTHETIC
}
@@ -1,20 +1,27 @@
package org.jetbrains.plugins.gradle.sync;
import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* UI control for showing difference between the gradle and intellij project structure.
@@ -24,6 +31,7 @@ import java.util.Collection;
*/
public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
private Tree myTree;
private GradleProjectStructureTreeModel myTreeModel;
private JPanel myContent;
@@ -52,14 +60,16 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
private void init() {
myContent = new JPanel(new GridBagLayout());
myTreeModel = new GradleProjectStructureTreeModel(getProject(), getProjectFacade(), getProjectStructureHelper());
Tree tree = new Tree(myTreeModel);
applyInitialAppearance(tree, (DefaultMutableTreeNode)myTreeModel.getRoot());
myTree = new Tree(myTreeModel);
applyInitialAppearance(myTree, (DefaultMutableTreeNode)myTreeModel.getRoot());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = constraints.weighty = 1;
myContent.add(tree, constraints);
myContent.setBackground(tree.getBackground());
myContent.add(myTree, constraints);
myContent.setBackground(myTree.getBackground());
CustomizationUtil.installPopupHandler(myTree, GradleConstants.ACTION_GROUP_SYNC_TREE, GradleConstants.SYNC_TREE_PLACE);
}
@NotNull
@@ -75,6 +85,25 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
int i = 1;
}
@Nullable
@Override
public Object getData(@NonNls String dataId) {
if (GradleDataKeys.SYNC_TREE_NODE.is(dataId)) {
TreePath[] paths = myTree.getSelectionPaths();
if (paths == null) {
return null;
}
List<GradleProjectStructureNode<?>> result = new ArrayList<GradleProjectStructureNode<?>>();
for (TreePath path : paths) {
result.add((GradleProjectStructureNode<?>)path.getLastPathComponent());
}
return result;
}
else {
return super.getData(dataId);
}
}
private static void applyInitialAppearance(@NotNull Tree tree, @NotNull DefaultMutableTreeNode node) {
if (node.getUserObject() == GradleProjectStructureTreeModel.DEPENDENCIES_NODE_DESCRIPTOR) {
tree.expandPath(new TreePath(node.getPath()));
@@ -8,6 +8,7 @@ import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.RootPolicy;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
import org.jetbrains.plugins.gradle.model.*;
@@ -37,20 +38,20 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
* <code>false</code> otherwise
*/
public boolean isIntellijLibraryDependencyExist(@NotNull final GradleLibraryDependencyId id) {
for (Module module : myFacade.getModules(myProject)) {
if (!id.getModuleName().equals(module.getName())) {
continue;
final Module module = findIntellijModuleByName(id.getModuleName());
if (module == null) {
return false;
}
RootPolicy<Boolean> visitor = new RootPolicy<Boolean>() {
@Override
public Boolean visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Boolean value) {
return id.getLibraryName().equals(libraryOrderEntry.getLibraryName());
}
RootPolicy<Boolean> visitor = new RootPolicy<Boolean>() {
@Override
public Boolean visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Boolean value) {
return id.getLibraryName().equals(libraryOrderEntry.getLibraryName());
}
};
for (OrderEntry entry : myFacade.getOrderEntries(module)) {
if (entry.accept(visitor, false)) {
return true;
}
};
for (OrderEntry entry : myFacade.getOrderEntries(module)) {
if (entry.accept(visitor, false)) {
return true;
}
}
return false;
@@ -64,29 +65,55 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
* <code>false</code> otherwise
*/
public boolean isGradleLibraryDependencyExist(@NotNull final GradleLibraryDependencyId id) {
return findLibraryDependency(id) != null;
}
@Nullable
public Module findIntellijModuleByName(@NotNull String name) {
for (Module module : myFacade.getModules(myProject)) {
if (name.equals(module.getName())) {
return module;
}
}
return null;
}
@Nullable
public GradleModule findGradleModuleByName(@NotNull String name) {
final GradleProject project = myModel.getGradleProject();
if (project == null) {
return false;
return null;
}
final Ref<Boolean> matched = new Ref<Boolean>();
for (GradleModule module : project.getModules()) {
if (name.equals(module.getName())) {
return module;
}
}
return null;
}
@Nullable
public GradleLibraryDependency findLibraryDependency(@NotNull final GradleLibraryDependencyId id) {
final GradleModule module = findGradleModuleByName(id.getModuleName());
if (module == null) {
return null;
}
final Ref<GradleLibraryDependency> ref = new Ref<GradleLibraryDependency>();
GradleEntityVisitor visitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
matched.set(id.getLibraryName().equals(dependency.getName()));
}
};
for (GradleModule module : project.getModules()) {
if (!id.getModuleName().equals(module.getName())) {
continue;
}
for (GradleDependency dependency : module.getDependencies()) {
dependency.invite(visitor);
if (matched.get()) {
return true;
if (id.getLibraryName().equals(dependency.getName())) {
ref.set(dependency);
}
}
return false;
};
for (GradleDependency dependency : module.getDependencies()) {
dependency.invite(visitor);
final GradleLibraryDependency result = ref.get();
if (result != null) {
return result;
}
}
return false;
return null;
}
}
@@ -10,6 +10,7 @@ import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.diff.*;
import org.jetbrains.plugins.gradle.model.GradleEntityType;
import org.jetbrains.plugins.gradle.model.GradleLibraryDependencyId;
import org.jetbrains.plugins.gradle.ui.GradleIcons;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
@@ -77,7 +78,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
myModuleDependencies.clear();
myModules.clear();
GradleProjectStructureNode<Project> root = buildNode(getProject(), getProject().getName(), myPlatformFacade.getProjectIcon());
GradleProjectStructureNode<Project> root
= buildNode(getProject(), GradleEntityType.PROJECT, getProject().getName(), myPlatformFacade.getProjectIcon());
final Collection<Module> modules = myPlatformFacade.getModules(getProject());
RootPolicy<LibraryOrderEntry> policy = new RootPolicy<LibraryOrderEntry>() {
@Override
@@ -86,7 +88,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
};
for (Module module : modules) {
final GradleProjectStructureNode<String> moduleNode = buildNode(module.getName(), GradleIcons.MODULE_ICON);
final GradleProjectStructureNode<String> moduleNode = buildNode(GradleEntityType.MODULE, module.getName(), GradleIcons.MODULE_ICON);
myModules.put(module.getName(), moduleNode); // Assuming that module names are unique.
List<LibraryOrderEntry> libraryDependencies = new ArrayList<LibraryOrderEntry>();
for (OrderEntry orderEntry : myPlatformFacade.getOrderEntries(module)) {
@@ -100,7 +102,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
if (id == null) {
continue;
}
dependenciesNode.add(buildNode(id, id.getLibraryName(), GradleIcons.LIB_ICON));
dependenciesNode.add(buildNode(id, GradleEntityType.LIBRARY_DEPENDENCY, id.getLibraryName(), GradleIcons.LIB_ICON));
}
moduleNode.add(dependenciesNode);
}
@@ -119,14 +121,18 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
return new GradleProjectStructureNodeDescriptor<T>(entity, name, icon);
}
private static GradleProjectStructureNode<String> buildNode(@NotNull String name, @NotNull Icon icon) {
return buildNode(name, name, icon);
private static GradleProjectStructureNode<String> buildNode(@NotNull GradleEntityType type, @NotNull String name, @NotNull Icon icon) {
return buildNode(name, type, name, icon);
}
private static <T> GradleProjectStructureNode<T> buildNode(@NotNull T entity, @NotNull String name, @NotNull Icon icon) {
return new GradleProjectStructureNode<T>(buildDescriptor(entity, name, icon));
private static <T> GradleProjectStructureNode<T> buildNode(@NotNull T entity,
@NotNull GradleEntityType type,
@NotNull String name,
@NotNull Icon icon)
{
return new GradleProjectStructureNode<T>(buildDescriptor(entity, name, icon), type);
}
private GradleProjectStructureNode<String> getDependenciesNode(@NotNull String moduleName) {
final GradleProjectStructureNode<String> cached = myModuleDependencies.get(moduleName);
if (cached != null) {
@@ -134,11 +140,11 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
GradleProjectStructureNode<String> moduleNode = myModules.get(moduleName);
if (moduleNode == null) {
moduleNode = buildNode(moduleName, GradleIcons.MODULE_ICON);
moduleNode = buildNode(GradleEntityType.MODULE, moduleName, GradleIcons.MODULE_ICON);
myModules.put(moduleName, moduleNode);
}
GradleProjectStructureNode<String> result = new GradleProjectStructureNode<String>(DEPENDENCIES_NODE_DESCRIPTOR);
GradleProjectStructureNode<String> result = new GradleProjectStructureNode<String>(DEPENDENCIES_NODE_DESCRIPTOR, GradleEntityType.SYNTHETIC);
moduleNode.add(result);
myModuleDependencies.put(moduleName, result);
@@ -184,7 +190,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
return;
}
}
GradleProjectStructureNode<GradleLibraryDependencyId> newNode = buildNode(id, id.getLibraryName(), GradleIcons.LIB_ICON);
GradleProjectStructureNode<GradleLibraryDependencyId> newNode
= buildNode(id, GradleEntityType.LIBRARY_DEPENDENCY, id.getLibraryName(), GradleIcons.LIB_ICON);
newNode.getDescriptor().setAttributes(attributes);
dependenciesNode.add(newNode);
nodeStructureChanged(dependenciesNode);
@@ -0,0 +1,18 @@
package org.jetbrains.plugins.gradle.ui;
import com.intellij.openapi.actionSystem.DataKey;
import java.util.Collection;
/**
* @author Denis Zhdanov
* @since 2/7/12 11:19 AM
*/
public class GradleDataKeys {
/** Key for obtaining currently selected nodes at the gradle 'sync project structure' tree. */
public static final DataKey<Collection<GradleProjectStructureNode<?>>> SYNC_TREE_NODE = DataKey.create("gradle.sync.tree.node");
private GradleDataKeys() {
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.ui;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
import org.jetbrains.plugins.gradle.model.GradleEntityType;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
@@ -16,11 +17,14 @@ import java.util.*;
public class GradleProjectStructureNode<T> extends DefaultMutableTreeNode implements Iterable<GradleProjectStructureNode<?>> {
private final Set<GradleProjectStructureChange> myConflictChanges = new HashSet<GradleProjectStructureChange>();
private final GradleProjectStructureNodeDescriptor<T> myDescriptor;
public GradleProjectStructureNode(@NotNull GradleProjectStructureNodeDescriptor<T> descriptor) {
private final GradleProjectStructureNodeDescriptor<T> myDescriptor;
private final GradleEntityType myType;
public GradleProjectStructureNode(@NotNull GradleProjectStructureNodeDescriptor<T> descriptor, @NotNull GradleEntityType type) {
super(descriptor);
myDescriptor = descriptor;
myType = type;
}
@NotNull
@@ -28,6 +32,11 @@ public class GradleProjectStructureNode<T> extends DefaultMutableTreeNode implem
return myDescriptor;
}
@NotNull
public GradleEntityType getType() {
return myType;
}
@Override
public GradleProjectStructureNode<?> getChildAt(int index) {
return (GradleProjectStructureNode)super.getChildAt(index);
@@ -41,10 +50,10 @@ public class GradleProjectStructureNode<T> extends DefaultMutableTreeNode implem
@Override
public void add(MutableTreeNode newChild) {
GradleProjectStructureNode<?> child = (GradleProjectStructureNode)newChild;
final String newText = child.getDescriptor().getText();
final String newName = child.getDescriptor().getName();
for (int i = 0; i < getChildCount(); i++) {
GradleProjectStructureNode<?> node = getChildAt(i);
if (newText.compareTo(node.getDescriptor().getText()) < 0) {
if (newName.compareTo(node.getDescriptor().getName()) < 0) {
insert(newChild, i);
return;
}
@@ -46,12 +46,7 @@ public class GradleProjectStructureNodeDescriptor<T> extends PresentableNodeDesc
return myData;
}
@NotNull
public String getText() {
return myName;
}
public void setText(@NotNull String name) {
public void setName(@NotNull String name) {
myName = name;
}
@@ -1,10 +1,7 @@
package org.jetbrains.plugins.gradle.util;
import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
/**
* Holds object representation of icons used at the <code>Gradle</code> plugin.
*
@@ -13,9 +10,13 @@ import javax.swing.*;
*/
public class GradleConstants {
@NonNls public static final String EXTENSION = "gradle";
@NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
@NonNls public static final String EXTENSION = "gradle";
@NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
@NonNls public static final String TOOL_WINDOW_TOOLBAR_PLACE = "GRADLE_SYNC_CHANGES_TOOLBAR";
@NonNls public static final String SYNC_TREE_PLACE = "GRADLE_SYNC_TREE_PLACE";
@NonNls public static final String ACTION_GROUP_SYNC_TREE = "Gradle.SyncTreeGroup";
private GradleConstants() {
}

Some files were not shown because too many files have changed in this diff Show More