mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
Generated
+2
-1
@@ -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" />
|
||||
|
||||
@@ -364,6 +364,8 @@ public def layoutCommunityPlugins(String home) {
|
||||
include(name: "**/*.jar")
|
||||
exclude(name: "**/ddmlib_1.jar")
|
||||
}
|
||||
|
||||
jar("android_rt.jar") {module("android-rt")}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+3
-1
@@ -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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+11
-10
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+34
-20
@@ -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() {
|
||||
|
||||
+25
-43
@@ -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
|
||||
|
||||
+20
-1
@@ -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>();
|
||||
|
||||
+12
-7
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+8
-7
@@ -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;
|
||||
}
|
||||
|
||||
+20
-1
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
+55
-56
@@ -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));
|
||||
}
|
||||
}
|
||||
+10
-8
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -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() {
|
||||
|
||||
+3
-3
@@ -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() {
|
||||
|
||||
+3
-3
@@ -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) {
|
||||
|
||||
+123
-120
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -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";
|
||||
|
||||
+1
@@ -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);
|
||||
}
|
||||
|
||||
+6
-1
@@ -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);
|
||||
}
|
||||
|
||||
+6
-1
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+16
@@ -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
|
||||
}
|
||||
}
|
||||
+152
@@ -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
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
+33
-4
@@ -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()));
|
||||
|
||||
+55
-28
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-11
@@ -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;
|
||||
}
|
||||
|
||||
+1
-6
@@ -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
Reference in New Issue
Block a user