mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge commit 'origin/master'
This commit is contained in:
Generated
+1
@@ -11,6 +11,7 @@
|
||||
<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/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$/plugins/android/jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/android/jps-plugin/android-jps-plugin.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" />
|
||||
|
||||
@@ -366,6 +366,10 @@ public def layoutCommunityPlugins(String home) {
|
||||
}
|
||||
|
||||
jar("android_rt.jar") {module("android-rt")}
|
||||
|
||||
dir("jps") {
|
||||
jar("android-jps-plugin.jar") { module("android-jps-plugin") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,11 @@
|
||||
package org.jetbrains.jps
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class JavaSdk extends Sdk {
|
||||
String jdkPath
|
||||
public interface JavaSdk {
|
||||
|
||||
def JavaSdk(Project project, String name, String jdkPath, Closure initializer) {
|
||||
super(project, name, initializer)
|
||||
this.jdkPath = jdkPath
|
||||
}
|
||||
String getJavacExecutable();
|
||||
|
||||
String getJavacExecutable() {
|
||||
return jdkPath + File.separator + "bin" + File.separator + "javac";
|
||||
}
|
||||
|
||||
String getJavaExecutable() {
|
||||
return jdkPath + File.separator + "bin" + File.separator + "java";
|
||||
}
|
||||
}
|
||||
String getJavaExecutable();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.jetbrains.jps
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class JavaSdkImpl extends Sdk implements JavaSdk {
|
||||
String jdkPath
|
||||
|
||||
def JavaSdkImpl(Project project, String name, String jdkPath, Closure initializer) {
|
||||
super(project, name, initializer)
|
||||
this.jdkPath = jdkPath
|
||||
}
|
||||
|
||||
String getJavacExecutable() {
|
||||
return jdkPath + File.separator + "bin" + File.separator + "javac";
|
||||
}
|
||||
|
||||
String getJavaExecutable() {
|
||||
return jdkPath + File.separator + "bin" + File.separator + "java";
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class Project {
|
||||
}
|
||||
|
||||
def JavaSdk createJavaSdk(String name, String path, Closure initializer) {
|
||||
def sdk = new JavaSdk(this, name, path, initializer)
|
||||
def sdk = new JavaSdkImpl(this, name, path, initializer)
|
||||
sdks[name] = sdk
|
||||
return sdk
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.jetbrains.jps.idea
|
||||
|
||||
import org.jetbrains.jps.JavaSdkImpl
|
||||
import org.jetbrains.jps.Project
|
||||
import org.jetbrains.jps.Sdk
|
||||
import org.jetbrains.jps.JavaSdk
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -14,6 +14,6 @@ class JavaSdkType extends SdkTypeService {
|
||||
|
||||
@Override
|
||||
Sdk createSdk(Project project, String name, String homePath, Node additionalData) {
|
||||
return new JavaSdk(project, name, homePath, {})
|
||||
return new JavaSdkImpl(project, name, homePath, {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,21 +92,21 @@ public class Alarm implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public void addRequest(final Runnable request, int delayMillis) {
|
||||
public void addRequest(final Runnable request, long delayMillis) {
|
||||
_addRequest(request, delayMillis, myThreadToUse == ThreadToUse.SWING_THREAD ? ModalityState.current() : null);
|
||||
}
|
||||
|
||||
public void addComponentRequest(Runnable request, int delay) {
|
||||
public void addComponentRequest(Runnable request, long delayMillis) {
|
||||
assert myActivationComponent != null;
|
||||
_addRequest(request, delay, ModalityState.stateForComponent(myActivationComponent));
|
||||
_addRequest(request, delayMillis, ModalityState.stateForComponent(myActivationComponent));
|
||||
}
|
||||
|
||||
public void addRequest(final Runnable request, int delayMillis, @Nullable final ModalityState modalityState) {
|
||||
public void addRequest(final Runnable request, long delayMillis, @Nullable final ModalityState modalityState) {
|
||||
LOG.assertTrue(myThreadToUse == ThreadToUse.SWING_THREAD);
|
||||
_addRequest(request, delayMillis, modalityState);
|
||||
}
|
||||
|
||||
private void _addRequest(final Runnable request, int delayMillis, ModalityState modalityState) {
|
||||
private void _addRequest(final Runnable request, long delayMillis, ModalityState modalityState) {
|
||||
synchronized (LOCK) {
|
||||
LOG.assertTrue(!myDisposed, "Already disposed");
|
||||
final Request requestToSchedule = new Request(request, modalityState, delayMillis);
|
||||
@@ -191,9 +191,9 @@ public class Alarm implements Disposable {
|
||||
private Runnable myTask;
|
||||
private final ModalityState myModalityState;
|
||||
private Future<?> myFuture;
|
||||
private final int myDelay;
|
||||
private final long myDelay;
|
||||
|
||||
private Request(final Runnable task, final ModalityState modalityState, int delayMillis) {
|
||||
private Request(final Runnable task, final ModalityState modalityState, long delayMillis) {
|
||||
myTask = task;
|
||||
myModalityState = modalityState;
|
||||
myDelay = delayMillis;
|
||||
|
||||
@@ -31,8 +31,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.ExtensionPoint;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.updateSettings.impl.CheckForUpdateResult;
|
||||
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
@@ -49,7 +47,6 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@SuppressWarnings({"CallToPrintStackTrace"})
|
||||
@@ -217,7 +214,7 @@ public class IdeaApplication {
|
||||
|
||||
if (UpdateChecker.isMyVeryFirstOpening() && UpdateChecker.checkNeeded()) {
|
||||
UpdateChecker.setMyVeryFirstOpening(false);
|
||||
updatePlugins(true);
|
||||
UpdateChecker.updateAndShowResult();
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@@ -229,23 +226,6 @@ public class IdeaApplication {
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
|
||||
private void updatePlugins(final boolean showConfirmation) {
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
app.executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final CheckForUpdateResult checkForUpdateResult = UpdateChecker.checkForUpdates();
|
||||
|
||||
final List<PluginDownloader> updatedPlugins = UpdateChecker.updatePlugins(false, null);
|
||||
app.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UpdateChecker.showUpdateResult(checkForUpdateResult, updatedPlugins, showConfirmation, true, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void loadProject() {
|
||||
|
||||
+30
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -419,13 +419,31 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
* <code>'Token'</code> here stands for the number of subsequent symbols that are represented using the same font by IJ editor.
|
||||
*/
|
||||
private void processNonFoldToken() {
|
||||
int limit = 3 * (myContext.tokenEndOffset - myContext.lineStartPosition.offset);
|
||||
int counter = 0;
|
||||
int startOffset = myContext.currentPosition.offset;
|
||||
while (myContext.currentPosition.offset < myContext.tokenEndOffset) {
|
||||
//for (int i = myContext.startOffset; i < myContext.endOffset; i++) {
|
||||
if (counter++ > limit) {
|
||||
String editorInfo = myEditor instanceof EditorImpl ? ((EditorImpl)myEditor).dumpState() : myEditor.getClass().toString();
|
||||
LogMessageEx.error(LOG, "Cycled soft wraps recalculation detected", String.format(
|
||||
"Start recalculation offset: %d, visible area width: %d, calculation context: %s, editor info: %s",
|
||||
startOffset, myVisibleAreaWidth, myContext, editorInfo));
|
||||
for (int i = myContext.currentPosition.offset; i < myContext.tokenEndOffset; i++) {
|
||||
char c = myContext.text.charAt(i);
|
||||
if (c == '\n') {
|
||||
myContext.onNewLine();
|
||||
}
|
||||
else {
|
||||
myContext.onNonLineFeedSymbol(c);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
int offset = myContext.currentPosition.offset;
|
||||
if (offset > myContext.rangeEndOffset) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (myContext.delayedSoftWrap != null && myContext.delayedSoftWrap.getStart() == offset) {
|
||||
processSoftWrap(myContext.delayedSoftWrap);
|
||||
myContext.delayedSoftWrap = null;
|
||||
@@ -442,7 +460,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
createSoftWrapIfPossible();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int newX = offsetToX(offset, c);
|
||||
if (myContext.exceedsVisualEdge(newX) && myContext.delayedSoftWrap == null) {
|
||||
createSoftWrapIfPossible();
|
||||
@@ -1119,6 +1137,14 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
public boolean notifyListenersOnLineStartPosition;
|
||||
public boolean skipToLineEnd;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "reserved width: " + reservedWidthInPixels + ", soft wrap start offset: " + softWrapStartOffset + ", range end offset: "
|
||||
+ rangeEndOffset + ", token offsets: [" + tokenStartOffset + "; " + tokenEndOffset + "], font type: " + fontType
|
||||
+ ", skip to line end: " + skipToLineEnd + ", delayed soft wrap: " + delayedSoftWrap + ", current position: "+ currentPosition
|
||||
+ "line start position: " + lineStartPosition;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
text = null;
|
||||
lineStartPosition = null;
|
||||
|
||||
@@ -23,10 +23,12 @@ import org.jdom.Element;
|
||||
public class ButtonInfo {
|
||||
private final String myName;
|
||||
private final String myUrl;
|
||||
private final boolean myDownload;
|
||||
|
||||
public ButtonInfo(Element element) {
|
||||
myName = element.getAttributeValue("name");
|
||||
myUrl = element.getAttributeValue("url");
|
||||
myDownload = element.getAttributeValue("download") != null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -36,4 +38,13 @@ public class ButtonInfo {
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* The button marked with 'download=true' attribute is hidden if patch is available.
|
||||
*
|
||||
* @return true if the button should be hidden when the patch is available.
|
||||
*/
|
||||
public boolean isDownload() {
|
||||
return myDownload;
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -22,6 +22,7 @@ import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
@@ -32,6 +33,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
@@ -143,6 +145,27 @@ public final class UpdateChecker {
|
||||
return settings.CHECK_NEEDED;
|
||||
}
|
||||
|
||||
public static ActionCallback updateAndShowResult() {
|
||||
final ActionCallback result = new ActionCallback();
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
app.executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final CheckForUpdateResult checkForUpdateResult = checkForUpdates();
|
||||
|
||||
final List<PluginDownloader> updatedPlugins = updatePlugins(false, null);
|
||||
app.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showUpdateResult(checkForUpdateResult, updatedPlugins, true, true, false);
|
||||
result.setDone();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<PluginDownloader> updatePlugins(final boolean showErrorDialog,
|
||||
final @Nullable PluginHostsConfigurable hostsConfigurable) {
|
||||
final List<PluginDownloader> downloaded = new ArrayList<PluginDownloader>();
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class UpdateCheckerComponent implements ApplicationComponent {
|
||||
private static final long CHECK_INTERVAL = DateFormatUtil.DAY;
|
||||
private final Alarm myCheckForUpdatesAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
private final Runnable myCheckRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UpdateChecker.updateAndShowResult().doWhenDone(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
queueNextUpdateCheck(CHECK_INTERVAL);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
queueNextUpdateCheck(UpdateChecker.checkNeeded()
|
||||
? CHECK_INTERVAL
|
||||
: UpdateSettings.getInstance().LAST_TIME_CHECKED - System.currentTimeMillis() + CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
private void queueNextUpdateCheck(long interval) {
|
||||
myCheckForUpdatesAlarm.addRequest(myCheckRunnable, interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeComponent() {
|
||||
Disposer.dispose(myCheckForUpdatesAlarm);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getComponentName() {
|
||||
return "UpdateCheckerComponent";
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -66,11 +66,14 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
}
|
||||
else {
|
||||
for (ButtonInfo info : buttons) {
|
||||
actions.add(new ButtonAction(info));
|
||||
if (!info.isDownload()) {
|
||||
actions.add(new ButtonAction(info));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the first button replaces the OK action
|
||||
for (int i = 1; i < buttons.size(); i++) {
|
||||
actions.add(new ButtonAction(buttons.get(i)));
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
<component>
|
||||
<implementation-class>com.intellij.ui.switcher.QuickAccessSettings</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>com.intellij.openapi.updateSettings.impl.UpdateCheckerComponent</implementation-class>
|
||||
</component>
|
||||
</application-components>
|
||||
<project-components>
|
||||
<component>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?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" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Groovy" level="project" />
|
||||
<orderEntry type="module" module-name="jps-model" />
|
||||
<orderEntry type="module" module-name="android-rt" />
|
||||
<orderEntry type="module" module-name="jps-builders" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.jps.android.AndroidFacetType
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.jps.android.AndroidSdkType
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.jps.android.AndroidBuilderService
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.jetbrains.jps.android;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.incremental.BuilderService;
|
||||
import org.jetbrains.jps.incremental.ModuleLevelBuilder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidBuilderService extends BuilderService {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends ModuleLevelBuilder> createModuleLevelBuilders(ExecutorService executorService) {
|
||||
return Arrays.asList(new AndroidSourceGeneratingBuilder());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.jetbrains.jps.android
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.jps.Module
|
||||
import org.jetbrains.jps.idea.Facet
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class AndroidFacet extends Facet {
|
||||
final Module module
|
||||
final String resFolderRelativePath
|
||||
|
||||
AndroidFacet(Module module, String name, String resFolderRelativePath) {
|
||||
this.module = module
|
||||
this.name = name;
|
||||
this.resFolderRelativePath = resFolderRelativePath
|
||||
}
|
||||
|
||||
File getResourceDir() {
|
||||
return findFileByRelativeModulePath(resFolderRelativePath, true)
|
||||
}
|
||||
|
||||
private File findFileByRelativeModulePath(String relativePath, boolean lookInContentRoot) {
|
||||
if (module.basePath != null) {
|
||||
def absPath = FileUtil.toSystemIndependentName(module.basePath + relativePath)
|
||||
def f = new File(absPath)
|
||||
|
||||
if (f.exists()) {
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
if (lookInContentRoot) {
|
||||
module.contentRoots.each {
|
||||
def absPath = FileUtil.toSystemIndependentName(contentRoot + relativePath)
|
||||
def f = new File(absPath)
|
||||
|
||||
if (f.exists()) {
|
||||
return f
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.jetbrains.jps.android
|
||||
|
||||
import org.jetbrains.jps.MacroExpander
|
||||
import org.jetbrains.jps.Module
|
||||
import org.jetbrains.jps.idea.Facet
|
||||
import org.jetbrains.jps.idea.FacetTypeService
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class AndroidFacetType extends FacetTypeService {
|
||||
public static final String ID = "android"
|
||||
|
||||
AndroidFacetType() {
|
||||
super(ID)
|
||||
}
|
||||
|
||||
@Override
|
||||
Facet createFacet(Module module, String name, Node facetConfiguration, MacroExpander macroExpander) {
|
||||
return new AndroidFacet(module, name, "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.jetbrains.jps.android
|
||||
|
||||
import org.jetbrains.jps.JavaSdk
|
||||
import org.jetbrains.jps.Project
|
||||
import org.jetbrains.jps.Sdk
|
||||
import org.jetbrains.jps.JavaSdkImpl
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class AndroidSdk extends Sdk implements JavaSdk {
|
||||
final String sdkPath;
|
||||
final String buildTargetHashString;
|
||||
final String javaSdkName;
|
||||
|
||||
AndroidSdk(Project project, String name, String sdkPath, String javaSdkName, String buildTargetHashString) {
|
||||
super(project, name, {})
|
||||
this.sdkPath = sdkPath
|
||||
this.buildTargetHashString = buildTargetHashString
|
||||
this.javaSdkName = javaSdkName;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getJavacExecutable() {
|
||||
def javaSdk = project.sdks[javaSdkName]
|
||||
return javaSdk instanceof JavaSdkImpl ? javaSdk.getJavacExecutable() : null
|
||||
}
|
||||
|
||||
@Override
|
||||
String getJavaExecutable() {
|
||||
def javaSdk = project.sdks[javaSdkName]
|
||||
return javaSdk instanceof JavaSdkImpl ? javaSdk.getJavaExecutable() : null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.jetbrains.jps.android
|
||||
|
||||
import org.jetbrains.jps.idea.SdkTypeService
|
||||
import org.jetbrains.jps.Sdk
|
||||
import org.jetbrains.jps.Project
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class AndroidSdkType extends SdkTypeService {
|
||||
AndroidSdkType() {
|
||||
super("Android SDK");
|
||||
}
|
||||
|
||||
@Override
|
||||
Sdk createSdk(Project project, String name, String homePath, Node additionalData) {
|
||||
def attributes = additionalData.attributes()
|
||||
if (attributes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
def buildTargetHashString = (String)attributes.get("sdk")
|
||||
def internalJdkName = (String)attributes.get("jdk")
|
||||
|
||||
if (internalJdkName == null || buildTargetHashString == null) {
|
||||
return null;
|
||||
}
|
||||
return new AndroidSdk(project, name, homePath, internalJdkName, buildTargetHashString)
|
||||
}
|
||||
}
|
||||
+498
@@ -0,0 +1,498 @@
|
||||
package org.jetbrains.jps.android;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.compiler.tools.AndroidIdl;
|
||||
import org.jetbrains.android.compiler.tools.AndroidRenderscript;
|
||||
import org.jetbrains.android.sdk.MessageBuildingSdkLog;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidCompilerMessageKind;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.*;
|
||||
import org.jetbrains.jps.idea.Facet;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.android.AndroidSourceGeneratingBuilder");
|
||||
|
||||
@NonNls private static final String BUILDER_NAME = "android-source-generator";
|
||||
@NonNls private static final String AIDL_EXTENSION = "aidl";
|
||||
@NonNls private static final String RENDERSCRIPT_EXTENSION = "rs";
|
||||
|
||||
public AndroidSourceGeneratingBuilder() {
|
||||
super(BuilderCategory.SOURCE_GENERATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return BUILDER_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
|
||||
if (context.isCompilingTests()) {
|
||||
return ModuleLevelBuilder.ExitCode.OK;
|
||||
}
|
||||
|
||||
try {
|
||||
return doBuild(context, chunk);
|
||||
}
|
||||
catch (ProjectBuildException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
String message = e.getMessage();
|
||||
|
||||
if (message == null) {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
//noinspection IOResourceOpenedButNotSafelyClosed
|
||||
e.printStackTrace(new PrintStream(out));
|
||||
message = "Internal error: \n" + out.toString();
|
||||
}
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message));
|
||||
throw new ProjectBuildException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ModuleLevelBuilder.ExitCode doBuild(CompileContext context, ModuleChunk chunk) throws Exception {
|
||||
final Map<File, AndroidFacet> idlFilesToCompile = new HashMap<File, AndroidFacet>();
|
||||
final Map<File, AndroidFacet> rsFilesToCompile = new HashMap<File, AndroidFacet>();
|
||||
final Set<Module> modules = new HashSet<Module>();
|
||||
|
||||
context.processFilesToRecompile(chunk, new FileProcessor() {
|
||||
@Override
|
||||
public boolean apply(Module module, File file, String sourceRoot) throws IOException {
|
||||
final AndroidFacet facet = getFacet(module);
|
||||
|
||||
if (facet == null) {
|
||||
return true;
|
||||
}
|
||||
final String ext = FileUtil.getExtension(file.getName());
|
||||
|
||||
if (AIDL_EXTENSION.equals(ext)) {
|
||||
idlFilesToCompile.put(file, facet);
|
||||
modules.add(facet.getModule());
|
||||
}
|
||||
else if (RENDERSCRIPT_EXTENSION.equals(ext)) {
|
||||
rsFilesToCompile.put(file, facet);
|
||||
modules.add(facet.getModule());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
final Map<Module, MyModuleData> moduleDataMap = computeModuleDatas(modules, context);
|
||||
|
||||
if (moduleDataMap == null) {
|
||||
return ExitCode.OK;
|
||||
}
|
||||
|
||||
if (!runAidlCompiler(context, idlFilesToCompile, moduleDataMap)) {
|
||||
return ExitCode.OK;
|
||||
}
|
||||
|
||||
if (!runRenderscriptCompiler(context, rsFilesToCompile, moduleDataMap)) {
|
||||
return ExitCode.OK;
|
||||
}
|
||||
|
||||
return ExitCode.OK;
|
||||
}
|
||||
|
||||
private static boolean runAidlCompiler(@NotNull final CompileContext context,
|
||||
@NotNull Map<File, AndroidFacet> files,
|
||||
@NotNull Map<Module, MyModuleData> moduleDataMap) {
|
||||
context.processMessage(new ProgressMessage("Processing AIDL files..."));
|
||||
|
||||
boolean success = true;
|
||||
|
||||
for (Map.Entry<File, AndroidFacet> entry : files.entrySet()) {
|
||||
final File file = entry.getKey();
|
||||
final Module module = entry.getValue().getModule();
|
||||
final String filePath = file.getPath();
|
||||
|
||||
final MyModuleData moduleData = moduleDataMap.get(module);
|
||||
|
||||
if (!LOG.assertTrue(moduleData != null)) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Internal error"));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
final File outputDirectory = moduleData.getOutputDirectory();
|
||||
final File aidlOutputDirectory = new File(outputDirectory, "generated-aidl");
|
||||
final IAndroidTarget target = moduleData.getAndroidTarget();
|
||||
|
||||
try {
|
||||
final File[] sourceRoots = getSourceRootsForModuleAndDependencies(module);
|
||||
final String[] sourceRootPaths = toPaths(sourceRoots);
|
||||
final String packageName = computePackageForFile(context, file);
|
||||
|
||||
if (packageName == null) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot compute package for file",
|
||||
filePath));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
final File outputFile = new File(aidlOutputDirectory, packageName.replace('.', File.separatorChar) +
|
||||
File.separator + FileUtil.getNameWithoutExtension(file) + ".java");
|
||||
final String outputFilePath = outputFile.getPath();
|
||||
final Map<AndroidCompilerMessageKind, List<String>> messages =
|
||||
AndroidIdl.execute(target, filePath, outputFilePath, sourceRootPaths);
|
||||
|
||||
addMessages(context, messages, filePath);
|
||||
|
||||
if (messages.get(AndroidCompilerMessageKind.ERROR).size() > 0) {
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
final String moduleName = getCannonicalModuleName(module);
|
||||
final SourceToOutputMapping sourceToOutputMap = context.getDataManager().getSourceToOutputMap(moduleName, false);
|
||||
sourceToOutputMap.update(filePath, outputFilePath);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
reportExceptionError(context, filePath, e);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean runRenderscriptCompiler(@NotNull final CompileContext context,
|
||||
@NotNull Map<File, AndroidFacet> files,
|
||||
@NotNull Map<Module, MyModuleData> moduleDataMap) {
|
||||
context.processMessage(new ProgressMessage("Processing Renderscript files..."));
|
||||
|
||||
boolean success = true;
|
||||
|
||||
for (Map.Entry<File, AndroidFacet> entry : files.entrySet()) {
|
||||
final File file = entry.getKey();
|
||||
final Module module = entry.getValue().getModule();
|
||||
|
||||
final MyModuleData moduleData = moduleDataMap.get(module);
|
||||
if (!LOG.assertTrue(moduleData != null)) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Internal error"));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
final File outputDirectory = moduleData.getOutputDirectory();
|
||||
final File rsOutputDirectory = new File(outputDirectory, "generated-rs");
|
||||
final File generatedResourcesDir = new File(outputDirectory, "generated-resources");
|
||||
|
||||
final IAndroidTarget target = moduleData.getAndroidTarget();
|
||||
final String sdkLocation = moduleData.getSdkLocation();
|
||||
final String filePath = file.getPath();
|
||||
|
||||
File tmpOutputDirectory = null;
|
||||
|
||||
try {
|
||||
tmpOutputDirectory = FileUtil.createTempDirectory("generated-rs-temp", null);
|
||||
final String depFolderPath = getDependencyFolder(context, file, tmpOutputDirectory);
|
||||
final File rawDir = new File(generatedResourcesDir, "raw");
|
||||
|
||||
final Map<AndroidCompilerMessageKind, List<String>> messages =
|
||||
AndroidRenderscript.execute(sdkLocation, target, filePath, tmpOutputDirectory.getPath(), depFolderPath, rawDir.getPath());
|
||||
|
||||
addMessages(context, messages, filePath);
|
||||
|
||||
if (messages.get(AndroidCompilerMessageKind.ERROR).size() > 0) {
|
||||
success = false;
|
||||
}
|
||||
else {
|
||||
final List<File> newFiles = new ArrayList<File>();
|
||||
AndroidCommonUtils.moveAllFiles(tmpOutputDirectory, rsOutputDirectory, newFiles);
|
||||
|
||||
final File bcFile = new File(rawDir, FileUtil.getNameWithoutExtension(file) + ".bc");
|
||||
if (bcFile.exists()) {
|
||||
newFiles.add(bcFile);
|
||||
}
|
||||
final List<String> newFilePaths = Arrays.asList(toPaths(newFiles.toArray(new File[newFiles.size()])));
|
||||
|
||||
final String moduleName = getCannonicalModuleName(module);
|
||||
final SourceToOutputMapping sourceToOutputMap = context.getDataManager().getSourceToOutputMap(moduleName, false);
|
||||
sourceToOutputMap.update(filePath, newFilePaths);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
reportExceptionError(context, filePath, e);
|
||||
success = false;
|
||||
}
|
||||
finally {
|
||||
if (tmpOutputDirectory != null) {
|
||||
FileUtil.delete(tmpOutputDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static void reportExceptionError(@NotNull CompileContext context, @NotNull String filePath, @NotNull Exception exception) {
|
||||
final String message = exception.getMessage();
|
||||
|
||||
if (message != null) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message, filePath));
|
||||
LOG.debug(exception);
|
||||
}
|
||||
else {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, exception));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getCannonicalModuleName(@NotNull Module module) {
|
||||
return module.getName().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getDependencyFolder(@NotNull CompileContext context, @NotNull File sourceFile, @NotNull File genFolder) {
|
||||
final RootDescriptor descriptor = context.getRootsIndex().getModuleAndRoot(sourceFile);
|
||||
if (descriptor == null) {
|
||||
return null;
|
||||
}
|
||||
final File sourceRoot = descriptor.root;
|
||||
|
||||
final File parent = FileUtil.getParentFile(sourceFile);
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parent.equals(sourceRoot)) {
|
||||
return genFolder.getPath();
|
||||
}
|
||||
final String relativePath = FileUtil.getRelativePath(sourceRoot, parent);
|
||||
assert relativePath != null;
|
||||
return genFolder.getPath() + '/' + relativePath;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Map<Module, MyModuleData> computeModuleDatas(@NotNull Collection<Module> modules, @NotNull CompileContext context)
|
||||
throws Exception {
|
||||
final Map<Module, MyModuleData> moduleDataMap = new HashMap<Module, MyModuleData>();
|
||||
|
||||
boolean success = true;
|
||||
|
||||
for (Module module : modules) {
|
||||
|
||||
final Sdk sdk = module.getSdk();
|
||||
if (!(sdk instanceof AndroidSdk)) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
|
||||
"Android SDK is not specified for module " + module.getName()));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
final AndroidSdk androidSdk = (AndroidSdk)sdk;
|
||||
|
||||
final IAndroidTarget target = parseAndroidTarget(androidSdk, context);
|
||||
if (target == null) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
|
||||
"Android SDK is invalid or not specified for module " + module.getName()));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
final File outputDir = context.getProjectPaths().getModuleOutputDir(module, false);
|
||||
if (outputDir == null) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
|
||||
"Cannot find output directory for module " + module.getName()));
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
moduleDataMap.put(module, new MyModuleData(outputDir, androidSdk.getSdkPath(), target));
|
||||
}
|
||||
|
||||
return success ? moduleDataMap : null;
|
||||
}
|
||||
|
||||
private static void addMessages(@NotNull CompileContext context,
|
||||
@NotNull Map<AndroidCompilerMessageKind, List<String>> messages,
|
||||
@Nullable String sourcePath) {
|
||||
for (Map.Entry<AndroidCompilerMessageKind, List<String>> entry : messages.entrySet()) {
|
||||
final AndroidCompilerMessageKind kind = entry.getKey();
|
||||
final BuildMessage.Kind buildMessageKind = toBuildMessageKind(kind);
|
||||
|
||||
if (buildMessageKind == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String message : entry.getValue()) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, buildMessageKind, message, sourcePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BuildMessage.Kind toBuildMessageKind(@NotNull AndroidCompilerMessageKind kind) {
|
||||
switch (kind) {
|
||||
case ERROR:
|
||||
return BuildMessage.Kind.ERROR;
|
||||
case INFORMATION:
|
||||
return BuildMessage.Kind.INFO;
|
||||
case WARNING:
|
||||
return BuildMessage.Kind.WARNING;
|
||||
default:
|
||||
LOG.error("unknown AndroidCompilerMessageKind object " + kind);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String computePackageForFile(@NotNull CompileContext context, @NotNull File file) throws IOException {
|
||||
final RootDescriptor descriptor = context.getRootsIndex().getModuleAndRoot(file);
|
||||
if (descriptor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String relPath = FileUtil.getRelativePath(descriptor.root, FileUtil.getParentFile(file));
|
||||
if (relPath == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FileUtil.toSystemIndependentName(relPath).replace('/', '.');
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static IAndroidTarget parseAndroidTarget(@NotNull AndroidSdk sdk, @NotNull CompileContext context) {
|
||||
final String targetHashString = sdk.getBuildTargetHashString();
|
||||
if (targetHashString == null) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
|
||||
"Cannot parse SDK " + sdk.getName() + ": build target is not specified"));
|
||||
return null;
|
||||
}
|
||||
|
||||
final MessageBuildingSdkLog log = new MessageBuildingSdkLog();
|
||||
final SdkManager manager = AndroidCommonUtils.createSdkManager(sdk.getSdkPath(), log);
|
||||
|
||||
if (manager == null) {
|
||||
final String message = log.getErrorMessage();
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
|
||||
"Android SDK is parsed incorrectly." +
|
||||
(message.length() > 0 ? " Parsing log:\n" + message : "")));
|
||||
return null;
|
||||
}
|
||||
|
||||
final IAndroidTarget target = manager.getTargetFromHashString(targetHashString);
|
||||
if (target == null) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
|
||||
"Cannot parse SDK '" + sdk.getName() + "': unknown target " + targetHashString));
|
||||
return null;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private static void fillSourceRoots(@NotNull Module module, @NotNull Set<Module> visited, @NotNull Set<File> result)
|
||||
throws IOException {
|
||||
visited.add(module);
|
||||
final AndroidFacet facet = getFacet(module);
|
||||
File resDir = null;
|
||||
|
||||
if (facet != null) {
|
||||
resDir = facet.getResourceDir();
|
||||
if (resDir != null) {
|
||||
resDir = resDir.getCanonicalFile();
|
||||
}
|
||||
}
|
||||
|
||||
for (String sourceRootPath : module.getSourceRoots()) {
|
||||
final File sourceRoot = new File(sourceRootPath).getCanonicalFile();
|
||||
|
||||
if (!sourceRoot.equals(resDir)) {
|
||||
result.add(sourceRoot);
|
||||
}
|
||||
}
|
||||
|
||||
for (ClasspathItem classpathItem : module.getClasspath(ClasspathKind.PRODUCTION_COMPILE)) {
|
||||
if (classpathItem instanceof Module) {
|
||||
final Module depModule = (Module)classpathItem;
|
||||
|
||||
if (!visited.contains(depModule)) {
|
||||
fillSourceRoots(depModule, visited, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static File[] getSourceRootsForModuleAndDependencies(@NotNull Module module) throws IOException {
|
||||
Set<File> result = new HashSet<File>();
|
||||
fillSourceRoots(module, new HashSet<Module>(), result);
|
||||
return result.toArray(new File[result.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Android Builder";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static AndroidFacet getFacet(@NotNull Module module) {
|
||||
AndroidFacet androidFacet = null;
|
||||
|
||||
for (Facet facet : module.getFacets().values()) {
|
||||
if (facet instanceof AndroidFacet) {
|
||||
androidFacet = (AndroidFacet)facet;
|
||||
}
|
||||
}
|
||||
return androidFacet;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String[] toPaths(@NotNull File[] files) {
|
||||
final String[] result = new String[files.length];
|
||||
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = files[i].getPath();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class MyModuleData {
|
||||
private final File myOutputDirectory;
|
||||
private final String mySdkLocation;
|
||||
private final IAndroidTarget myAndroidTarget;
|
||||
|
||||
private MyModuleData(@NotNull File outputDirectory,
|
||||
@NotNull String sdkLocation,
|
||||
@NotNull IAndroidTarget androidTarget) {
|
||||
myOutputDirectory = outputDirectory;
|
||||
mySdkLocation = sdkLocation;
|
||||
myAndroidTarget = androidTarget;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public File getOutputDirectory() {
|
||||
return myOutputDirectory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public IAndroidTarget getAndroidTarget() {
|
||||
return myAndroidTarget;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getSdkLocation() {
|
||||
return mySdkLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,9 @@
|
||||
package org.jetbrains.android.compiler.tools;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidCompilerMessageKind;
|
||||
import org.jetbrains.android.util.ExecutionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,6 +34,8 @@ import java.util.Map;
|
||||
* @author Alexey Efimov
|
||||
*/
|
||||
public final class AndroidIdl {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.tools.AndroidIdl");
|
||||
|
||||
private AndroidIdl() {
|
||||
}
|
||||
|
||||
@@ -51,6 +55,8 @@ public final class AndroidIdl {
|
||||
}
|
||||
commands.add(file);
|
||||
commands.add(outFile);
|
||||
|
||||
LOG.info(AndroidCommonUtils.command2string(commands));
|
||||
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(commands));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.jetbrains.android.compiler.tools;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidCompilerMessageKind;
|
||||
import org.jetbrains.android.util.ExecutionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidRenderscript {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidRenderscriptCompiler");
|
||||
|
||||
public static Map<AndroidCompilerMessageKind, List<String>> execute(@NotNull final String sdkLocation,
|
||||
@NotNull IAndroidTarget target,
|
||||
@NotNull String sourceFilePath,
|
||||
@NotNull final String genFolderPath,
|
||||
@Nullable String depFolderPath,
|
||||
@NotNull final String rawDirPath)
|
||||
throws IOException {
|
||||
final List<String> command = new ArrayList<String>();
|
||||
command.add(
|
||||
FileUtil.toSystemDependentName(sdkLocation + '/' + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER + SdkConstants.FN_RENDERSCRIPT));
|
||||
command.add("-I");
|
||||
command.add(target.getPath(IAndroidTarget.ANDROID_RS_CLANG));
|
||||
command.add("-I");
|
||||
command.add(target.getPath(IAndroidTarget.ANDROID_RS));
|
||||
command.add("-p");
|
||||
command.add(FileUtil.toSystemDependentName(genFolderPath));
|
||||
command.add("-o");
|
||||
command.add(FileUtil.toSystemDependentName(rawDirPath));
|
||||
|
||||
command.add("-target-api");
|
||||
command.add(Integer.toString(target.getVersion().getApiLevel()));
|
||||
|
||||
if (depFolderPath != null) {
|
||||
command.add("-d");
|
||||
command.add(FileUtil.toSystemDependentName(depFolderPath));
|
||||
}
|
||||
|
||||
command.add("-MD");
|
||||
command.add(FileUtil.toSystemDependentName(sourceFilePath));
|
||||
|
||||
LOG.info(AndroidCommonUtils.command2string(command));
|
||||
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(command));
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -21,11 +21,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Eugene.Kudelevsky
|
||||
* Date: Aug 25, 2009
|
||||
* Time: 5:54:47 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class MessageBuildingSdkLog implements ISdkLog {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.sdk.MessageBuildingSdkLog");
|
||||
@@ -1,8 +1,15 @@
|
||||
package org.jetbrains.android.util;
|
||||
|
||||
import com.android.sdklib.ISdkLog;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
@@ -11,7 +18,7 @@ import java.util.Iterator;
|
||||
*/
|
||||
public class AndroidCommonUtils {
|
||||
@NonNls public static final Object MANIFEST_JAVA_FILE_NAME = "Manifest.java";
|
||||
public static final String R_JAVA_FILENAME = "R.java";
|
||||
@NonNls public static final String R_JAVA_FILENAME = "R.java";
|
||||
|
||||
private AndroidCommonUtils() {
|
||||
}
|
||||
@@ -29,4 +36,37 @@ public class AndroidCommonUtils {
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SdkManager createSdkManager(@NotNull String path, @NotNull ISdkLog log) {
|
||||
path = FileUtil.toSystemDependentName(path);
|
||||
|
||||
final File f = new File(path);
|
||||
if (!f.exists() || !f.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final File platformsDir = new File(f, SdkConstants.FD_PLATFORMS);
|
||||
if (!platformsDir.exists() || !platformsDir.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SdkManager.createManager(path + File.separatorChar, log);
|
||||
}
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,6 +189,12 @@
|
||||
<externalAnnotator language="JAVA" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
|
||||
<externalAnnotator language="XML" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
|
||||
<externalAnnotator language="TEXT" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
|
||||
|
||||
<compileServer.plugin jar-path="jps/android-jps-plugin.jar"/>
|
||||
<compileServer.plugin jar-path="android-rt.jar"/>
|
||||
|
||||
<compileServer.plugin jar-path="sdklib.jar"/>
|
||||
<compileServer.plugin jar-path="../../../../../community/plugins/android/lib/sdklib.jar"/>
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
|
||||
@@ -20,6 +20,7 @@ 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.compiler.tools.AndroidRenderscript;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidRootUtil;
|
||||
@@ -448,13 +449,19 @@ public class AndroidAutogenerator {
|
||||
|
||||
try {
|
||||
tempOutDir = FileUtil.createTempDirectory("android_renderscript_autogeneration", "tmp");
|
||||
final VirtualFile vTempOutDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempOutDir);
|
||||
|
||||
final Map<CompilerMessageCategory, List<String>> messages = AndroidRenderscriptCompiler.
|
||||
launchRenderscriptCompiler(module.getProject(), item.mySdkLocation, item.myTarget, file, tempOutDir.getPath(), item.myRawDirPath);
|
||||
final String depFolderPath =
|
||||
vTempOutDir != null ? AndroidRenderscriptCompiler.getDependencyFolder(context.getProject(), file, vTempOutDir) : null;
|
||||
|
||||
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
|
||||
AndroidRenderscript
|
||||
.execute(item.mySdkLocation, item.myTarget, file.getPath(), tempOutDir.getPath(), depFolderPath,
|
||||
item.myRawDirPath));
|
||||
|
||||
if (messages.get(CompilerMessageCategory.ERROR).size() == 0) {
|
||||
final List<File> newFiles = new ArrayList<File>();
|
||||
moveAllFiles(tempOutDir, new File(item.myGenDirPath), newFiles);
|
||||
AndroidCommonUtils.moveAllFiles(tempOutDir, new File(item.myGenDirPath), newFiles);
|
||||
|
||||
for (File newFile : newFiles) {
|
||||
final VirtualFile newVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(newFile);
|
||||
@@ -502,22 +509,6 @@ public class AndroidAutogenerator {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
+14
-55
@@ -2,31 +2,26 @@ package org.jetbrains.android.compiler;
|
||||
|
||||
import com.android.AndroidConstants;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
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.diagnostic.Logger;
|
||||
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.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.compiler.tools.AndroidRenderscript;
|
||||
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.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -40,8 +35,7 @@ import java.util.*;
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidRenderscriptCompiler");
|
||||
|
||||
|
||||
private static final GenerationItem[] EMPTY_GENERATION_ITEM_ARRAY = {};
|
||||
|
||||
@Nullable
|
||||
@@ -190,13 +184,15 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
|
||||
}
|
||||
|
||||
for (final VirtualFile sourceFile : genItem.myFiles) {
|
||||
final String depFolderOsPath = getDependencyFolder(context.getProject(), sourceFile, outputRootDirectory);
|
||||
|
||||
try {
|
||||
final Map<CompilerMessageCategory, List<String>> messages = launchRenderscriptCompiler(context.getProject(),
|
||||
genItem.mySdkLocation,
|
||||
genItem.myAndroidTarget,
|
||||
sourceFile,
|
||||
genRootPath,
|
||||
genItem.myRawDirPath);
|
||||
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
|
||||
AndroidRenderscript
|
||||
.execute(genItem.mySdkLocation, genItem.myAndroidTarget, sourceFile.getPath(), genRootPath,
|
||||
depFolderOsPath,
|
||||
genItem.myRawDirPath));
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
if (context.getProject().isDisposed()) {
|
||||
@@ -235,47 +231,10 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
FileUtil.toSystemDependentName(sdkLocation + '/' + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER + SdkConstants.FN_RENDERSCRIPT));
|
||||
command.add("-I");
|
||||
command.add(target.getPath(IAndroidTarget.ANDROID_RS_CLANG));
|
||||
command.add("-I");
|
||||
command.add(target.getPath(IAndroidTarget.ANDROID_RS));
|
||||
command.add("-p");
|
||||
command.add(FileUtil.toSystemDependentName(genFolderPath));
|
||||
command.add("-o");
|
||||
command.add(FileUtil.toSystemDependentName(rawDirPath));
|
||||
|
||||
final String sourceFilePath = FileUtil.toSystemDependentName(sourceFile.getPath());
|
||||
|
||||
final VirtualFile genFolder = LocalFileSystem.getInstance().refreshAndFindFileByPath(FileUtil.toSystemIndependentName(genFolderPath));
|
||||
if (genFolder != null) {
|
||||
final String dependencyFolderPath = getDependencyFolder(project, sourceFile, genFolder);
|
||||
if (dependencyFolderPath != null) {
|
||||
command.add("-d");
|
||||
command.add(FileUtil.toSystemDependentName(dependencyFolderPath));
|
||||
}
|
||||
}
|
||||
|
||||
command.add("-MD");
|
||||
command.add(sourceFilePath);
|
||||
|
||||
LOG.info(AndroidCommonUtils.command2string(command));
|
||||
return AndroidCompileUtil.execute(ArrayUtil.toStringArray(command));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getDependencyFolder(@NotNull final Project project,
|
||||
@NotNull final VirtualFile sourceFile,
|
||||
@NotNull final VirtualFile genFolder) {
|
||||
static String getDependencyFolder(@NotNull final Project project,
|
||||
@NotNull final VirtualFile sourceFile,
|
||||
@NotNull final VirtualFile genFolder) {
|
||||
final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
|
||||
final VirtualFile sourceRoot = index.getSourceRootForFile(sourceFile);
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.android.actions.AndroidEnableDdmsAction;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.android.util.BufferingFileWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -152,7 +153,7 @@ public class AndroidSdk {
|
||||
|
||||
@Nullable
|
||||
public static AndroidSdk parse(@NotNull String path, @NotNull ISdkLog log) {
|
||||
final SdkManager manager = AndroidSdkUtils.createSdkManager(path, log);
|
||||
final SdkManager manager = AndroidCommonUtils.createSdkManager(path, log);
|
||||
return manager != null ? new AndroidSdk(manager, path) : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
package org.jetbrains.android.sdk;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.ISdkLog;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -36,12 +34,12 @@ import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -55,7 +53,7 @@ public class AndroidSdkUtils {
|
||||
}
|
||||
|
||||
public static boolean isAndroidSdk(@NotNull String path) {
|
||||
return createSdkManager(path, new EmptySdkLog()) != null;
|
||||
return AndroidCommonUtils.createSdkManager(path, new EmptySdkLog()) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -370,21 +368,4 @@ public class AndroidSdkUtils {
|
||||
public static void openModuleDependenciesConfigurable(final Module module) {
|
||||
ProjectSettingsService.getInstance(module.getProject()).openModuleDependenciesSettings(module, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SdkManager createSdkManager(@NotNull String path, @NotNull ISdkLog log) {
|
||||
path = FileUtil.toSystemDependentName(path);
|
||||
|
||||
final File f = new File(path);
|
||||
if (!f.exists() || !f.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final File platformsDir = new File(f, SdkConstants.FD_PLATFORMS);
|
||||
if (!platformsDir.exists() || !platformsDir.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return SdkManager.createManager(path + File.separatorChar, log);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<!--Generic application services-->
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.util.GradleLibraryManager"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.task.GradleTaskManager"/>
|
||||
<applicationService serviceInterface="org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager"
|
||||
serviceImplementation="org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl"/>
|
||||
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.PlatformFacade"
|
||||
@@ -74,6 +75,9 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesDetector</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<actions>
|
||||
|
||||
+13
-9
@@ -2,6 +2,7 @@ package org.jetbrains.plugins.gradle.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -21,13 +22,13 @@ public abstract class AbstractGradleLinkedProjectAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final String path = getLinkedProjectPath(e.getDataContext());
|
||||
final boolean visible = path != null;
|
||||
final Pair<Project, String> pair = deriveProjects(e.getDataContext());
|
||||
final boolean visible = pair != null;
|
||||
e.getPresentation().setVisible(visible);
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
doUpdate(e.getPresentation(), path);
|
||||
doUpdate(e.getPresentation(), pair.first, pair.second);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,16 +37,16 @@ public abstract class AbstractGradleLinkedProjectAction extends AnAction {
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
final String path = getLinkedProjectPath(e.getDataContext());
|
||||
if (path == null) {
|
||||
final Pair<Project, String> pair = deriveProjects(e.getDataContext());
|
||||
if (pair == null) {
|
||||
e.getPresentation().setVisible(false);
|
||||
return;
|
||||
}
|
||||
doActionPerformed(project, path);
|
||||
doActionPerformed(project, pair.second);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static String getLinkedProjectPath(@Nullable DataContext context) {
|
||||
private static Pair<Project, String> deriveProjects(@Nullable DataContext context) {
|
||||
if (context == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -56,9 +57,12 @@ public abstract class AbstractGradleLinkedProjectAction extends AnAction {
|
||||
}
|
||||
|
||||
final String path = GradleSettings.getInstance(project).LINKED_PROJECT_FILE_PATH;
|
||||
return (StringUtil.isEmpty(path) || !new File(path).isFile()) ? null : path;
|
||||
if (StringUtil.isEmpty(path) || !new File(path).isFile()) {
|
||||
return null;
|
||||
}
|
||||
return new Pair<Project, String>(project, path);
|
||||
}
|
||||
|
||||
protected abstract void doUpdate(@NotNull Presentation presentation, @NotNull String linkedProjectPath);
|
||||
protected abstract void doUpdate(@NotNull Presentation presentation, @NotNull Project project, @NotNull String linkedProjectPath);
|
||||
protected abstract void doActionPerformed(@NotNull Project project, @NotNull String linkedProjectPath);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.jetbrains.plugins.gradle.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
@@ -32,7 +30,7 @@ public class GradleOpenScriptAction extends AbstractGradleLinkedProjectAction im
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doUpdate(@NotNull Presentation presentation, @NotNull String linkedProjectPath) {
|
||||
protected void doUpdate(@NotNull Presentation presentation, @NotNull Project project, @NotNull String linkedProjectPath) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+14
-24
@@ -1,17 +1,16 @@
|
||||
package org.jetbrains.plugins.gradle.action;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskManager;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
/**
|
||||
* Forces the 'gradle' plugin to retrieve the most up-to-date info about the
|
||||
@@ -21,34 +20,25 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/23/12 3:48 PM
|
||||
*/
|
||||
public class GradleRefreshProjectAction extends AbstractGradleLinkedProjectAction implements DumbAware {
|
||||
public class GradleRefreshProjectAction extends AbstractGradleLinkedProjectAction implements DumbAware, AnAction.TransparentUpdate {
|
||||
|
||||
private final AtomicBoolean myInProgress = new AtomicBoolean();
|
||||
|
||||
public GradleRefreshProjectAction() {
|
||||
getTemplatePresentation().setText(GradleBundle.message("gradle.action.refresh.project.text"));
|
||||
getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.refresh.project.description"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doUpdate(@NotNull Presentation presentation, @NotNull String linkedProjectPath) {
|
||||
presentation.setEnabled(!myInProgress.get());
|
||||
protected void doUpdate(@NotNull Presentation presentation, @NotNull Project project, @NotNull String linkedProjectPath) {
|
||||
boolean enabled = false;
|
||||
final GradleTaskManager taskManager = ServiceManager.getService(GradleTaskManager.class);
|
||||
if (taskManager != null) {
|
||||
enabled = !taskManager.hasTaskOfTypeInProgress(GradleTaskType.RESOLVE_PROJECT);
|
||||
}
|
||||
presentation.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull final Project project, @NotNull final String linkedProjectPath) {
|
||||
myInProgress.set(true);
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, GradleBundle.message("gradle.sync.progress.text")) {
|
||||
@Override
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
try {
|
||||
GradleResolveProjectTask task = new GradleResolveProjectTask(project, linkedProjectPath, true);
|
||||
task.execute(indicator);
|
||||
}
|
||||
finally {
|
||||
myInProgress.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
GradleUtil.refreshProject(project);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-40
@@ -1,14 +1,10 @@
|
||||
package org.jetbrains.plugins.gradle.importing;
|
||||
|
||||
import com.intellij.execution.rmi.RemoteUtil;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.ide.util.projectWizard.WizardContext;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
@@ -17,7 +13,6 @@ import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
|
||||
import com.intellij.projectImport.ProjectImportBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -26,11 +21,9 @@ import org.jetbrains.plugins.gradle.config.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.model.GradleEntity;
|
||||
import org.jetbrains.plugins.gradle.model.GradleModule;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiException;
|
||||
import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
|
||||
import org.jetbrains.plugins.gradle.ui.GradleIcons;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
@@ -156,38 +149,7 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder<GradleProje
|
||||
final Ref<String> errorReason = new Ref<String>();
|
||||
try {
|
||||
final Project project = getProject(wizardContext);
|
||||
ProgressManager.getInstance().run(new Task.Modal(project, GradleBundle.message("gradle.import.progress.text"), true) {
|
||||
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
|
||||
@Override
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
GradleResolveProjectTask task = new GradleResolveProjectTask(project, myProjectFile.getAbsolutePath(), false);
|
||||
task.execute(indicator);
|
||||
myGradleProject = task.getProject();
|
||||
if (myGradleProject != null) {
|
||||
return;
|
||||
}
|
||||
final Throwable error = task.getError();
|
||||
if (error == null) {
|
||||
return;
|
||||
}
|
||||
Throwable unwrapped = RemoteUtil.unwrap(error);
|
||||
String reason = unwrapped.getLocalizedMessage();
|
||||
if (!StringUtil.isEmpty(reason)) {
|
||||
errorReason.set(reason);
|
||||
}
|
||||
if (unwrapped.getClass() == NoClassDefFoundError.class) {
|
||||
errorReason.set(GradleBundle.message("gradle.import.text.incomplete.tooling.api"));
|
||||
}
|
||||
else if (unwrapped.getClass() == GradleApiException.class) {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project. Reason: gradle api threw an exception:\n"
|
||||
+ ((GradleApiException)unwrapped).getOriginalReason()
|
||||
);
|
||||
}
|
||||
else {
|
||||
GradleLog.LOG.warn("Can't resolve gradle project", unwrapped);
|
||||
}
|
||||
}
|
||||
});
|
||||
myGradleProject = GradleUtil.refreshProject(project, myProjectFile.getAbsolutePath(), errorReason, false, true);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new ConfigurationException(e.getMessage(), GradleBundle.message("gradle.import.text.error.cannot.parse.project"));
|
||||
|
||||
+9
@@ -9,6 +9,15 @@ import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
*/
|
||||
public interface GradleProgressNotificationManager {
|
||||
|
||||
/**
|
||||
* Allows to register given listener to listen events from all tasks.
|
||||
*
|
||||
* @param listener listener to register
|
||||
* @return <code>true</code> if given listener was not registered before for the given key;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean addNotificationListener(@NotNull GradleTaskNotificationListener listener);
|
||||
|
||||
/**
|
||||
* Allows to register given listener within the current manager for listening events from the task with the target id.
|
||||
*
|
||||
|
||||
+25
-4
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -19,9 +20,15 @@ public class GradleProgressNotificationManagerImpl extends RemoteObject
|
||||
implements GradleProgressNotificationManager, RemoteGradleProgressNotificationManager
|
||||
{
|
||||
|
||||
private final ConcurrentMap<GradleTaskNotificationListener, Set<GradleTaskId>> myListeners
|
||||
private final ConcurrentMap<GradleTaskNotificationListener, Set<GradleTaskId>/* EMPTY_SET as a sign of 'all ids' */> myListeners
|
||||
= new ConcurrentHashMap<GradleTaskNotificationListener, Set<GradleTaskId>>();
|
||||
|
||||
@Override
|
||||
public boolean addNotificationListener(@NotNull GradleTaskNotificationListener listener) {
|
||||
Set<GradleTaskId> dummy = Collections.emptySet();
|
||||
return myListeners.put(listener, dummy) == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addNotificationListener(@NotNull GradleTaskId taskId, @NotNull GradleTaskNotificationListener listener) {
|
||||
Set<GradleTaskId> ids = null;
|
||||
@@ -41,10 +48,22 @@ public class GradleProgressNotificationManagerImpl extends RemoteObject
|
||||
return myListeners.remove(listener) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQueued(@NotNull GradleTaskId id) {
|
||||
for (Map.Entry<GradleTaskNotificationListener, Set<GradleTaskId>> entry : myListeners.entrySet()) {
|
||||
final Set<GradleTaskId> ids = entry.getValue();
|
||||
if (Collections.EMPTY_SET == ids || ids.contains(id)) {
|
||||
entry.getKey().onQueued(id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NotNull GradleTaskId id) {
|
||||
for (Map.Entry<GradleTaskNotificationListener, Set<GradleTaskId>> entry : myListeners.entrySet()) {
|
||||
if (entry.getValue().contains(id)) {
|
||||
final Set<GradleTaskId> ids = entry.getValue();
|
||||
if (Collections.EMPTY_SET == ids || ids.contains(id)) {
|
||||
entry.getKey().onStart(id);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +72,8 @@ public class GradleProgressNotificationManagerImpl extends RemoteObject
|
||||
@Override
|
||||
public void onStatusChange(@NotNull GradleTaskNotificationEvent event) {
|
||||
for (Map.Entry<GradleTaskNotificationListener, Set<GradleTaskId>> entry : myListeners.entrySet()) {
|
||||
if (entry.getValue().contains(event.getId())) {
|
||||
final Set<GradleTaskId> ids = entry.getValue();
|
||||
if (Collections.EMPTY_SET == ids || ids.contains(event.getId())) {
|
||||
entry.getKey().onStatusChange(event);
|
||||
}
|
||||
}
|
||||
@@ -62,7 +82,8 @@ public class GradleProgressNotificationManagerImpl extends RemoteObject
|
||||
@Override
|
||||
public void onEnd(@NotNull GradleTaskId id) {
|
||||
for (Map.Entry<GradleTaskNotificationListener, Set<GradleTaskId>> entry : myListeners.entrySet()) {
|
||||
if (entry.getValue().contains(id)) {
|
||||
final Set<GradleTaskId> ids = entry.getValue();
|
||||
if (Collections.EMPTY_SET == ids || ids.contains(id)) {
|
||||
entry.getKey().onEnd(id);
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -11,6 +11,16 @@ import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
*/
|
||||
public interface GradleTaskNotificationListener {
|
||||
|
||||
/**
|
||||
* Notifies that task with the given id is queued for the execution.
|
||||
* <p/>
|
||||
* 'Queued' here means that intellij process-local codebase receives request to execute the target task and even has not been
|
||||
* sent it to the slave gradle api process.
|
||||
*
|
||||
* @param id target task's id
|
||||
*/
|
||||
void onQueued(@NotNull GradleTaskId id);
|
||||
|
||||
/**
|
||||
* Notifies that task with the given id is about to be started.
|
||||
*
|
||||
|
||||
+5
@@ -8,6 +8,11 @@ import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
* @since 11/10/11 12:18 PM
|
||||
*/
|
||||
public class GradleTaskNotificationListenerAdapter implements GradleTaskNotificationListener {
|
||||
|
||||
@Override
|
||||
public void onQueued(@NotNull GradleTaskId id) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NotNull GradleTaskId id) {
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskAware;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Serves as a facade for working with
|
||||
@@ -18,7 +16,7 @@ import java.util.Collection;
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/8/11 10:52 AM
|
||||
*/
|
||||
public interface GradleApiFacade extends Remote {
|
||||
public interface GradleApiFacade extends Remote, GradleTaskAware {
|
||||
|
||||
/**
|
||||
* Exposes <code>'resolve gradle project'</code> service that works at another process.
|
||||
@@ -45,23 +43,4 @@ public interface GradleApiFacade extends Remote {
|
||||
* @throws RemoteException in case of unexpected I/O exception during processing
|
||||
*/
|
||||
void applyProgressManager(@NotNull RemoteGradleProgressNotificationManager progressManager) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Asks remote gradle process to check if a task with the given id is being executed right now.
|
||||
*
|
||||
* @param id target task's id
|
||||
* @return <code>true</code> if a task with the given id is executed at the moment; <code>false</code> otherwise
|
||||
* @throws RemoteException in case of unexpected I/O exception during processing
|
||||
*/
|
||||
boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Allows to ask remote gradle process for the ids of the tasks with the given type being executed now.
|
||||
*
|
||||
* @param type target task type
|
||||
* @return ids of the tasks of the target type being executed at the moment (if any)
|
||||
* @throws RemoteException in case of unexpected I/O exception during processing
|
||||
*/
|
||||
@NotNull
|
||||
Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) throws RemoteException;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,9 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl;
|
||||
import org.jetbrains.plugins.gradle.remote.impl.GradleApiFacadeImpl;
|
||||
import org.jetbrains.plugins.gradle.remote.wrapper.GradleApiFacadeWrapper;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLibraryManager;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
@@ -69,8 +71,8 @@ public class GradleApiFacadeManager {
|
||||
private final AtomicReference<RemoteGradleProgressNotificationManager> myExportedProgressManager
|
||||
= new AtomicReference<RemoteGradleProgressNotificationManager>();
|
||||
|
||||
private final GradleLibraryManager myGradleLibraryManager;
|
||||
private final RemoteGradleProgressNotificationManager myProgressManager;
|
||||
@NotNull private final GradleLibraryManager myGradleLibraryManager;
|
||||
@NotNull private final GradleProgressNotificationManagerImpl myProgressManager;
|
||||
|
||||
// Please note that we don't use RemoteGradleProcessSettings as the 'Configuration' type parameter here because we need
|
||||
// to apply the settings to the newly created process. I.e. every time new process is created we need to call
|
||||
@@ -80,7 +82,7 @@ public class GradleApiFacadeManager {
|
||||
|
||||
public GradleApiFacadeManager(@NotNull GradleLibraryManager gradleLibraryManager, @NotNull GradleProgressNotificationManager manager) {
|
||||
myGradleLibraryManager = gradleLibraryManager;
|
||||
myProgressManager = (RemoteGradleProgressNotificationManager)manager;
|
||||
myProgressManager = (GradleProgressNotificationManagerImpl)manager;
|
||||
mySupport = new RemoteProcessSupport<Object, GradleApiFacade, Object>(GradleApiFacade.class) {
|
||||
@Override
|
||||
protected void fireModificationCountChanged() {
|
||||
@@ -223,10 +225,11 @@ public class GradleApiFacadeManager {
|
||||
myFacade.compareAndSet(pair, null);
|
||||
}
|
||||
|
||||
GradleApiFacade result = mySupport.acquire(this, "");
|
||||
if (result == null) {
|
||||
final GradleApiFacade facade = mySupport.acquire(this, "");
|
||||
if (facade == null) {
|
||||
throw new IllegalStateException("Can't obtain facade to working with gradle api at the remote process");
|
||||
}
|
||||
final GradleApiFacade result = new GradleApiFacadeWrapper(facade, myProgressManager);
|
||||
Pair<GradleApiFacade, RemoteGradleProcessSettings> newPair
|
||||
= new Pair<GradleApiFacade, RemoteGradleProcessSettings>(result, getRemoteSettings());
|
||||
if (!myFacade.compareAndSet(null, newPair)) {
|
||||
|
||||
+6
-1
@@ -18,6 +18,9 @@ import java.rmi.RemoteException;
|
||||
public interface RemoteGradleProgressNotificationManager extends Remote {
|
||||
|
||||
RemoteGradleProgressNotificationManager NULL_OBJECT = new RemoteGradleProgressNotificationManager() {
|
||||
@Override
|
||||
public void onQueued(@NotNull GradleTaskId id) throws RemoteException {
|
||||
}
|
||||
@Override
|
||||
public void onStart(@NotNull GradleTaskId id) {
|
||||
}
|
||||
@@ -28,7 +31,9 @@ public interface RemoteGradleProgressNotificationManager extends Remote {
|
||||
public void onEnd(@NotNull GradleTaskId id) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void onQueued(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
void onStart(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
void onStatusChange(@NotNull GradleTaskNotificationEvent event) throws RemoteException;
|
||||
|
||||
@@ -2,12 +2,10 @@ package org.jetbrains.plugins.gradle.remote;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskAware;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Generic interface with common functionality for all remote services that work with gradle tooling api.
|
||||
@@ -15,28 +13,8 @@ import java.util.Collection;
|
||||
* @author Denis Zhdanov
|
||||
* @since 8/9/11 3:19 PM
|
||||
*/
|
||||
public interface RemoteGradleService extends Remote {
|
||||
public interface RemoteGradleService extends Remote, GradleTaskAware {
|
||||
|
||||
/**
|
||||
* Allows to check if current service executes the target task.
|
||||
*
|
||||
* @param id target task's id
|
||||
* @return <code>true</code> if a task with the given id is executed at the moment by the current service;
|
||||
* <code>false</code> otherwise
|
||||
* @throws RemoteException as required by RMI
|
||||
*/
|
||||
boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Allows to ask current service for the ids of the tasks with the given type being executed now.
|
||||
*
|
||||
* @param type target task type
|
||||
* @return ids of the tasks of the target type being executed at the moment by the current service (if any)
|
||||
* @throws RemoteException as required by RMI
|
||||
*/
|
||||
@NotNull
|
||||
Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Provides the service settings to use.
|
||||
*
|
||||
|
||||
+20
-7
@@ -142,21 +142,30 @@ public class GradleApiFacadeImpl extends RemoteServer implements GradleApiFacade
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) throws RemoteException {
|
||||
Set<GradleTaskId> result = null;
|
||||
public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
|
||||
Map<GradleTaskType, Set<GradleTaskId>> result = null;
|
||||
for (RemoteGradleService service : myRemotes.values()) {
|
||||
final Collection<GradleTaskId> tasks = service.getTasksInProgress(type);
|
||||
final Map<GradleTaskType, Set<GradleTaskId>> tasks = service.getTasksInProgress();
|
||||
if (tasks.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (result == null) {
|
||||
result = new HashSet<GradleTaskId>();
|
||||
result = new HashMap<GradleTaskType, Set<GradleTaskId>>();
|
||||
}
|
||||
for (Map.Entry<GradleTaskType, Set<GradleTaskId>> entry : tasks.entrySet()) {
|
||||
Set<GradleTaskId> ids = result.get(entry.getKey());
|
||||
if (ids == null) {
|
||||
result.put(entry.getKey(), ids = new HashSet<GradleTaskId>());
|
||||
}
|
||||
ids.addAll(entry.getValue());
|
||||
}
|
||||
result.addAll(tasks);
|
||||
}
|
||||
return result == null ? Collections.<GradleTaskId>emptySet() : result;
|
||||
if (result == null) {
|
||||
result = Collections.emptyMap();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void applySettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
|
||||
mySettings.set(settings);
|
||||
@@ -208,6 +217,10 @@ public class GradleApiFacadeImpl extends RemoteServer implements GradleApiFacade
|
||||
myManager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQueued(@NotNull GradleTaskId id) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NotNull GradleTaskId id) {
|
||||
try {
|
||||
|
||||
+4
-5
@@ -81,11 +81,10 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<GradleTaskId> getTasksInProgress(@NotNull GradleTaskType type) {
|
||||
if (type != GradleTaskType.RESOLVE_PROJECT || myTasksInProgress.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return new HashSet<GradleTaskId>(myTasksInProgress);
|
||||
public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
|
||||
Map<GradleTaskType, Set<GradleTaskId>> result = new HashMap<GradleTaskType, Set<GradleTaskId>>();
|
||||
result.put(GradleTaskType.RESOLVE_PROJECT, new HashSet<GradleTaskId>(myTasksInProgress));
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package org.jetbrains.plugins.gradle.remote.wrapper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacade;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class acts as a point where target remote gradle services are proxied.
|
||||
* <p/>
|
||||
* Check service wrapper contracts for more details.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 2/8/12 7:21 PM
|
||||
*/
|
||||
public class GradleApiFacadeWrapper implements GradleApiFacade {
|
||||
|
||||
@NotNull private final GradleApiFacade myDelegate;
|
||||
@NotNull private final GradleProgressNotificationManagerImpl myNotificationManager;
|
||||
|
||||
public GradleApiFacadeWrapper(@NotNull GradleApiFacade delegate, @NotNull GradleProgressNotificationManagerImpl notificationManager) {
|
||||
myDelegate = delegate;
|
||||
myNotificationManager = notificationManager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GradleProjectResolver getResolver() throws RemoteException, IllegalStateException {
|
||||
return new GradleProjectResolverWrapper(myDelegate.getResolver(), myNotificationManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
|
||||
myDelegate.applySettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyProgressManager(@NotNull RemoteGradleProgressNotificationManager progressManager) throws RemoteException {
|
||||
myDelegate.applyProgressManager(progressManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
|
||||
return myDelegate.isTaskInProgress(id);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
|
||||
return myDelegate.getTasksInProgress();
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package org.jetbrains.plugins.gradle.remote.wrapper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiException;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleProjectResolver;
|
||||
import org.jetbrains.plugins.gradle.remote.RemoteGradleProcessSettings;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskId;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskManager;
|
||||
import org.jetbrains.plugins.gradle.task.GradleTaskType;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Intercepts calls to the target {@link GradleProjectResolver} and
|
||||
* {@link GradleTaskManager#onQueued(GradleTaskId) updates 'queued' task status}.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 2/8/12 7:21 PM
|
||||
*/
|
||||
public class GradleProjectResolverWrapper implements GradleProjectResolver {
|
||||
|
||||
@NotNull private final GradleProjectResolver myResolver;
|
||||
@NotNull private final GradleProgressNotificationManagerImpl myNotificationManager;
|
||||
|
||||
public GradleProjectResolverWrapper(@NotNull GradleProjectResolver resolver,
|
||||
@NotNull GradleProgressNotificationManagerImpl notificationManager)
|
||||
{
|
||||
myResolver = resolver;
|
||||
myNotificationManager = notificationManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GradleProject resolveProjectInfo(@NotNull GradleTaskId id, @NotNull String projectPath, boolean downloadLibraries)
|
||||
throws RemoteException, GradleApiException, IllegalArgumentException, IllegalStateException
|
||||
{
|
||||
myNotificationManager.onQueued(id);
|
||||
return myResolver.resolveProjectInfo(id, projectPath, downloadLibraries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSettings(@NotNull RemoteGradleProcessSettings settings) throws RemoteException {
|
||||
myResolver.setSettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotificationListener(@NotNull GradleTaskNotificationListener notificationListener) throws RemoteException {
|
||||
myResolver.setNotificationListener(notificationListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException {
|
||||
return myResolver.isTaskInProgress(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException {
|
||||
return myResolver.getTasksInProgress();
|
||||
}
|
||||
}
|
||||
+60
-2
@@ -1,10 +1,68 @@
|
||||
package org.jetbrains.plugins.gradle.sync;
|
||||
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.util.Alarm;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* Detects project structure changes and triggers linked gradle project update.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 11/3/11 3:57 PM
|
||||
*/
|
||||
public class GradleProjectStructureChangesDetector {
|
||||
public class GradleProjectStructureChangesDetector extends AbstractProjectComponent {
|
||||
|
||||
private static final int REFRESH_DELAY_MILLIS = (int)TimeUnit.SECONDS.toMillis(2);
|
||||
|
||||
private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
private final AtomicLong myStartRefreshTime = new AtomicLong();
|
||||
private final RefreshRequest myRequest = new RefreshRequest();
|
||||
|
||||
public GradleProjectStructureChangesDetector(@NotNull Project project) {
|
||||
super(project);
|
||||
subscribeToRootChanges(project);
|
||||
}
|
||||
|
||||
private void subscribeToRootChanges(@NotNull Project project) {
|
||||
project.getMessageBus().connect(project).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
|
||||
@Override
|
||||
public void beforeRootsChange(ModuleRootEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
scheduleUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void scheduleUpdate() {
|
||||
myStartRefreshTime.set(System.currentTimeMillis() + REFRESH_DELAY_MILLIS);
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(myRequest, REFRESH_DELAY_MILLIS + 16);
|
||||
}
|
||||
|
||||
private class RefreshRequest implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myProject.isInitialized()) {
|
||||
return;
|
||||
}
|
||||
myAlarm.cancelAllRequests();
|
||||
final long diff = System.currentTimeMillis() - myStartRefreshTime.get();
|
||||
if (diff < 0) {
|
||||
myAlarm.addRequest(this, (int)-diff);
|
||||
return;
|
||||
}
|
||||
GradleUtil.refreshProject(myProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public abstract class AbstractGradleTask implements GradleTask {
|
||||
}
|
||||
finally {
|
||||
for (GradleTaskNotificationListener listener : listeners) {
|
||||
progressManager.addNotificationListener(getId(), listener);
|
||||
progressManager.removeNotificationListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents service that exposes information about the tasks being processed.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 2/8/12 1:46 PM
|
||||
*/
|
||||
public interface GradleTaskAware {
|
||||
|
||||
/**
|
||||
* Allows to check if current service executes the target task.
|
||||
*
|
||||
* @param id target task's id
|
||||
* @return <code>true</code> if a task with the given id is executed at the moment by the current service;
|
||||
* <code>false</code> otherwise
|
||||
* @throws RemoteException as required by RMI
|
||||
*/
|
||||
boolean isTaskInProgress(@NotNull GradleTaskId id) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Allows to ask current service for all tasks being executed at the moment.
|
||||
*
|
||||
* @return ids of all tasks being executed at the moment grouped by type
|
||||
* @throws RemoteException as required by RMI
|
||||
*/
|
||||
@NotNull
|
||||
Map<GradleTaskType, Set<GradleTaskId>> getTasksInProgress() throws RemoteException;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package org.jetbrains.plugins.gradle.task;
|
||||
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent;
|
||||
import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager;
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Provides gradle tasks monitoring and management facilities.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 2/8/12 1:52 PM
|
||||
*/
|
||||
public class GradleTaskManager implements GradleTaskNotificationListener {
|
||||
|
||||
/**
|
||||
* We receive information about the tasks being enqueued to the slave gradle projects here. However, there is a possible
|
||||
* situation when particular task has been sent to execution but remote side has not been responding for a while. There at least
|
||||
* two possible explanations then:
|
||||
* <pre>
|
||||
* <ul>
|
||||
* <li>The task is still in progress (e.g. great number of libraries is being downloaded);</li>
|
||||
* <li>Remote side has fallen (uncaught exception; manual slave gradle process kill etc);</li>
|
||||
* </ul>
|
||||
* </pre>
|
||||
* We need to distinguish between them, so, we perform 'task pings' if any task is executed too long. Current constant holds
|
||||
* criteria of 'too long execution'.
|
||||
*/
|
||||
private static final long REFRESH_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(10);
|
||||
private static final int DETECT_HANGED_TASKS_FREQUENCY_MILLIS = (int)TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
@NotNull private final ConcurrentMap<GradleTaskId, Long> myTasksInProgress = new ConcurrentHashMap<GradleTaskId, Long>();
|
||||
@NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
|
||||
@NotNull private final GradleApiFacadeManager myFacadeManager;
|
||||
|
||||
public GradleTaskManager(@NotNull GradleApiFacadeManager facadeManager, @NotNull GradleProgressNotificationManager notificationManager) {
|
||||
myFacadeManager = facadeManager;
|
||||
notificationManager.addNotificationListener(this);
|
||||
myAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (Long limit : myTasksInProgress.values()) {
|
||||
if (limit <= System.currentTimeMillis()) {
|
||||
update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(this, DETECT_HANGED_TASKS_FREQUENCY_MILLIS);
|
||||
}
|
||||
}
|
||||
}, DETECT_HANGED_TASKS_FREQUENCY_MILLIS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to check if any task of the given type is being executed at the moment.
|
||||
*
|
||||
* @param type target task type
|
||||
* @return <code>true</code> if any task of the given type is being executed at the moment;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean hasTaskOfTypeInProgress(@NotNull GradleTaskType type) {
|
||||
for (GradleTaskId id : myTasksInProgress.keySet()) {
|
||||
if (type.equals(id.getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQueued(@NotNull GradleTaskId id) {
|
||||
myTasksInProgress.put(id, System.currentTimeMillis() + REFRESH_DELAY_MILLIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NotNull GradleTaskId id) {
|
||||
myTasksInProgress.put(id, System.currentTimeMillis() + REFRESH_DELAY_MILLIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChange(@NotNull GradleTaskNotificationEvent event) {
|
||||
myTasksInProgress.put(event.getId(), System.currentTimeMillis() + REFRESH_DELAY_MILLIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnd(@NotNull GradleTaskId id) {
|
||||
myTasksInProgress.remove(id);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
try {
|
||||
final Map<GradleTaskType, Set<GradleTaskId>> currentState = myFacadeManager.getFacade().getTasksInProgress();
|
||||
myTasksInProgress.clear();
|
||||
for (Set<GradleTaskId> ids : currentState.values()) {
|
||||
for (GradleTaskId id : ids) {
|
||||
myTasksInProgress.put(id, System.currentTimeMillis() + REFRESH_DELAY_MILLIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
GradleLog.LOG.warn(String.format("Can't refresh active tasks. Reason: %s", GradleUtil.buildErrorMessage(e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,36 @@
|
||||
package org.jetbrains.plugins.gradle.util;
|
||||
|
||||
import com.intellij.execution.rmi.RemoteUtil;
|
||||
import com.intellij.ide.actions.OpenProjectFileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileTypeDescriptor;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.BalloonBuilder;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettings;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
import org.jetbrains.plugins.gradle.remote.GradleApiException;
|
||||
import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask;
|
||||
import org.jetbrains.plugins.gradle.ui.GradleIcons;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -26,27 +41,6 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class GradleUtil {
|
||||
|
||||
/**
|
||||
* We use this class in order to avoid static initialisation of the wrapped object - it loads number of pico container-based
|
||||
* dependencies that are unavailable to the slave gradle project, so, we don't want to get unexpected NPE there.
|
||||
*/
|
||||
private static class DescriptorHolder {
|
||||
public static final FileChooserDescriptor GRADLE_BUILD_FILE_CHOOSER_DESCRIPTOR = new OpenProjectFileChooserDescriptor(true) {
|
||||
@Override
|
||||
public boolean isFileSelectable(VirtualFile file) {
|
||||
return GradleConstants.DEFAULT_SCRIPT_NAME.equals(file.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
|
||||
if (!super.isFileVisible(file, showHiddenFiles)) {
|
||||
return false;
|
||||
}
|
||||
return file.isDirectory() || GradleConstants.EXTENSION.equals(file.getExtension());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private GradleUtil() {
|
||||
}
|
||||
|
||||
@@ -96,4 +90,133 @@ public class GradleUtil {
|
||||
}
|
||||
balloon.show(new RelativePoint(component, new Point(x, y)), position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the {@link #refreshProject(Project, String, Ref, boolean, boolean)} with the following defaults:
|
||||
* <pre>
|
||||
* <ul>
|
||||
* <li>target gradle project path is retrieved from the {@link GradleSettings gradle settings} associated with the given project;</li>
|
||||
* <li>refresh process is run in background;</li>
|
||||
* <li>any problem occurred during the refresh is reported to the {@link GradleLog#LOG};</li>
|
||||
* </ul>
|
||||
* </pre>
|
||||
*
|
||||
* @param project target intellij project to use
|
||||
*/
|
||||
public static void refreshProject(@NotNull Project project) {
|
||||
final GradleSettings settings = GradleSettings.getInstance(project);
|
||||
final String linkedProjectPath = settings.LINKED_PROJECT_FILE_PATH;
|
||||
if (StringUtil.isEmpty(linkedProjectPath)) {
|
||||
return;
|
||||
}
|
||||
Ref<String> errorHolder = new Ref<String>();
|
||||
refreshProject(project, linkedProjectPath, errorHolder, true, false);
|
||||
final String error = errorHolder.get();
|
||||
if (!StringUtil.isEmpty(error)) {
|
||||
GradleLog.LOG.warn(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link RemoteUtil#unwrap(Throwable) unwraps} given exception if possible and builds error message for it.
|
||||
*
|
||||
* @param e exception to process
|
||||
* @return error message for the given exception
|
||||
*/
|
||||
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"})
|
||||
public static String buildErrorMessage(@NotNull Throwable e) {
|
||||
Throwable unwrapped = RemoteUtil.unwrap(e);
|
||||
String reason = unwrapped.getLocalizedMessage();
|
||||
if (!StringUtil.isEmpty(reason)) {
|
||||
return reason;
|
||||
}
|
||||
else if (unwrapped.getClass() == GradleApiException.class) {
|
||||
return String.format("gradle api threw an exception: %s", ((GradleApiException)unwrapped).getOriginalReason());
|
||||
}
|
||||
else {
|
||||
StringWriter writer = new StringWriter();
|
||||
unwrapped.printStackTrace(new PrintWriter(writer));
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Queries slave gradle process to refresh target gradle project.
|
||||
*
|
||||
* @param project target intellij project to use
|
||||
* @param gradleProjectPath path of the target gradle project's file
|
||||
* @param errorHolder holder for the error message that describes a problem occurred during the refresh (if any)
|
||||
* @param resolveLibraries flag that identifies whether gradle libraries should be resolved during the refresh
|
||||
* @return the most up-to-date gradle project (if any)
|
||||
*/
|
||||
@Nullable
|
||||
public static GradleProject refreshProject(@NotNull final Project project,
|
||||
@NotNull final String gradleProjectPath,
|
||||
@NotNull final Ref<String> errorHolder,
|
||||
final boolean resolveLibraries,
|
||||
final boolean modal)
|
||||
{
|
||||
final Ref<GradleProject> gradleProject = new Ref<GradleProject>();
|
||||
final TaskUnderProgress task = new TaskUnderProgress() {
|
||||
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"})
|
||||
@Override
|
||||
public void execute(@NotNull ProgressIndicator indicator) {
|
||||
GradleResolveProjectTask task = new GradleResolveProjectTask(project, gradleProjectPath, resolveLibraries);
|
||||
task.execute(indicator);
|
||||
gradleProject.set(task.getProject());
|
||||
final Throwable error = task.getError();
|
||||
if (error == null) {
|
||||
return;
|
||||
}
|
||||
final String message = buildErrorMessage(error);
|
||||
errorHolder.set(String.format("Can't resolve gradle project at '%s'. Reason: %s", gradleProjectPath, message));
|
||||
}
|
||||
};
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (modal) {
|
||||
ProgressManager.getInstance().run(new Task.Modal(project, GradleBundle.message("gradle.import.progress.text"), true) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
task.execute(indicator);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, GradleBundle.message("gradle.sync.progress.text")) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
task.execute(indicator);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return gradleProject.get();
|
||||
}
|
||||
|
||||
private interface TaskUnderProgress {
|
||||
void execute(@NotNull ProgressIndicator indicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* We use this class in order to avoid static initialisation of the wrapped object - it loads number of pico container-based
|
||||
* dependencies that are unavailable to the slave gradle project, so, we don't want to get unexpected NPE there.
|
||||
*/
|
||||
private static class DescriptorHolder {
|
||||
public static final FileChooserDescriptor GRADLE_BUILD_FILE_CHOOSER_DESCRIPTOR = new OpenProjectFileChooserDescriptor(true) {
|
||||
@Override
|
||||
public boolean isFileSelectable(VirtualFile file) {
|
||||
return GradleConstants.DEFAULT_SCRIPT_NAME.equals(file.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
|
||||
if (!super.isFileVisible(file, showHiddenFiles)) {
|
||||
return false;
|
||||
}
|
||||
return file.isDirectory() || GradleConstants.EXTENSION.equals(file.getExtension());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn17;
|
||||
|
||||
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
|
||||
|
||||
/**
|
||||
* since not all constants are available from svnkit & constants are fixed
|
||||
*/
|
||||
@@ -57,6 +59,10 @@ public enum WorkingCopyFormat {
|
||||
}
|
||||
|
||||
public static WorkingCopyFormat getInstance(final int value) {
|
||||
// somewhy 1.7 wc format can also be 29
|
||||
if (ISVNWCDb.WC_FORMAT_17 == value) {
|
||||
return ONE_DOT_SEVEN;
|
||||
}
|
||||
if (ONE_DOT_FIVE.getFormat() == value) {
|
||||
return ONE_DOT_FIVE;
|
||||
} else if (ONE_DOT_FOUR.getFormat() == value) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.idea.svn17;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.CommittedChangesProvider;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.VcsConfiguration;
|
||||
@@ -13,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn17.history.SvnChangeList;
|
||||
import org.jetbrains.idea.svn17.history.SvnRepositoryLocation;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
@@ -21,6 +23,12 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class SvnCommittedViewTest extends SvnTestCase {
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
SvnConfiguration17.getInstance(myProject).DETECT_NESTED_COPIES = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd() throws Exception {
|
||||
@@ -36,6 +44,7 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
checkin();
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
@@ -67,6 +76,7 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
checkin();
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
@@ -88,13 +98,17 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
// r1, addition without history
|
||||
checkin();
|
||||
|
||||
final String d1Path = new File(d1.getPath()).getAbsolutePath();
|
||||
File dir = new File(d1.getPath());
|
||||
final String d1Path = dir.getAbsolutePath();
|
||||
verify(runSvn("delete", d1Path));
|
||||
boolean created = dir.mkdir();
|
||||
Assert.assertTrue(created);
|
||||
verify(runSvn("add", d1Path));
|
||||
|
||||
checkin();
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
@@ -123,6 +137,7 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
checkin();
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
@@ -155,6 +170,7 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
checkin();
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
@@ -180,6 +196,7 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
verify(runSvn("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"));
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
@@ -209,6 +226,7 @@ public class SvnCommittedViewTest extends SvnTestCase {
|
||||
checkin();
|
||||
|
||||
final SvnVcs17 vcs = SvnVcs17.getInstance(myProject);
|
||||
vcs.invokeRefreshSvnRoots(false);
|
||||
final CommittedChangesProvider<SvnChangeList,ChangeBrowserSettings> committedChangesProvider = vcs.getCommittedChangesProvider();
|
||||
final List<SvnChangeList> changeListList =
|
||||
committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(),
|
||||
|
||||
@@ -43,6 +43,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
@Test
|
||||
public void testAdd() throws Throwable {
|
||||
final LocalChangeList newL = myChangeListManager.addChangeList("newOne", null);
|
||||
sleepABit();
|
||||
myDirtyScopeManager.markEverythingDirty();
|
||||
myChangeListManager.ensureUpToDate(false);
|
||||
|
||||
@@ -50,6 +51,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
final VirtualFile file = createFileInCommand("a.txt", "old content");
|
||||
sleepABit();
|
||||
|
||||
ensureAddedToNativeList();
|
||||
|
||||
@@ -66,6 +68,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
@Test
|
||||
public void testDeleted() throws Throwable {
|
||||
final LocalChangeList newL = myChangeListManager.addChangeList("newOne", null);
|
||||
sleepABit();
|
||||
myDirtyScopeManager.markEverythingDirty();
|
||||
myChangeListManager.ensureUpToDate(false);
|
||||
|
||||
@@ -74,9 +77,10 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
||||
final VirtualFile file = createFileInCommand("a.txt", "old content");
|
||||
sleepABit();
|
||||
checkin();
|
||||
deleteFileInCommand(file);
|
||||
|
||||
sleepABit();
|
||||
ensureAddedToNativeList();
|
||||
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "D a.txt");
|
||||
@@ -85,6 +89,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
@Test
|
||||
public void testEdit() throws Throwable {
|
||||
final LocalChangeList newL = myChangeListManager.addChangeList("newOne", null);
|
||||
sleepABit();
|
||||
myDirtyScopeManager.markEverythingDirty();
|
||||
myChangeListManager.ensureUpToDate(false);
|
||||
|
||||
@@ -92,9 +97,10 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
final VirtualFile file = createFileInCommand("a.txt", "old content");
|
||||
sleepABit();
|
||||
checkin();
|
||||
editFileInCommand(myProject, file, "111");
|
||||
|
||||
sleepABit();
|
||||
ensureAddedToNativeList();
|
||||
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "M a.txt");
|
||||
@@ -103,7 +109,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
@Test
|
||||
public void testEditAndMove() throws Throwable {
|
||||
final LocalChangeList newL = myChangeListManager.addChangeList("newOne", null);
|
||||
|
||||
sleepABit();
|
||||
myDirtyScopeManager.markEverythingDirty();
|
||||
myChangeListManager.ensureUpToDate(false);
|
||||
|
||||
@@ -112,14 +118,16 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
||||
final VirtualFile file = createFileInCommand("a.txt", "old content");
|
||||
sleepABit();
|
||||
checkin();
|
||||
editFileInCommand(myProject, file, "111");
|
||||
|
||||
sleepABit();
|
||||
ensureAddedToNativeList();
|
||||
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "M a.txt");
|
||||
|
||||
renameFileInCommand(file, "b.txt");
|
||||
sleepABit();
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
|
||||
|
||||
ensureAddedToNativeList();
|
||||
@@ -130,6 +138,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
@Test
|
||||
public void testMove() throws Throwable {
|
||||
final LocalChangeList newL = myChangeListManager.addChangeList("newOne", null);
|
||||
sleepABit();
|
||||
myDirtyScopeManager.markEverythingDirty();
|
||||
myChangeListManager.ensureUpToDate(false);
|
||||
|
||||
@@ -138,9 +147,11 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
||||
final VirtualFile file = createFileInCommand("a.txt", "old content");
|
||||
sleepABit();
|
||||
checkin();
|
||||
|
||||
renameFileInCommand(file, "b.txt");
|
||||
sleepABit();
|
||||
ensureAddedToNativeList();
|
||||
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
|
||||
@@ -149,6 +160,7 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
@Test
|
||||
public void testMoveMove() throws Throwable {
|
||||
final LocalChangeList newL = myChangeListManager.addChangeList("newOne", null);
|
||||
sleepABit();
|
||||
myDirtyScopeManager.markEverythingDirty();
|
||||
myChangeListManager.ensureUpToDate(false);
|
||||
|
||||
@@ -157,18 +169,30 @@ public class SvnNativeListsTest extends SvnTestCase {
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
|
||||
final VirtualFile file = createFileInCommand("a.txt", "old content");
|
||||
sleepABit();
|
||||
checkin();
|
||||
|
||||
renameFileInCommand(file, "b.txt");
|
||||
sleepABit();
|
||||
ensureAddedToNativeList();
|
||||
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
|
||||
|
||||
renameFileInCommand(file, "c.txt");
|
||||
sleepABit();
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + c.txt", "D a.txt");
|
||||
|
||||
ensureAddedToNativeList();
|
||||
|
||||
verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + c.txt", "D a.txt");
|
||||
}
|
||||
|
||||
private void sleepABit() {
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.jetbrains.idea.svn17;
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.idea.Bombed;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.VcsConfiguration;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
@@ -17,10 +19,7 @@ import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -95,8 +94,13 @@ public class SvnRenameTest extends SvnTestCase {
|
||||
verifyChange(changes.get(2), "child" + File.separatorChar + "grandChild", "childnew" + File.separatorChar + "grandChild");
|
||||
verifyChange(changes.get(3), "child" + File.separatorChar + "grandChild" + File.separatorChar + "b.txt", "childnew" + File.separatorChar + "grandChild" + File.separatorChar + "b.txt");
|
||||
|
||||
VirtualFile oldChild = myWorkingCopyDir.findChild("child");
|
||||
Assert.assertEquals(FileStatus.DELETED, changeListManager.getStatus(oldChild));
|
||||
// there is no such directory any more
|
||||
/*VirtualFile oldChild = myWorkingCopyDir.findChild("child");
|
||||
if (oldChild == null) {
|
||||
myWorkingCopyDir.refresh(false, true);
|
||||
oldChild = myWorkingCopyDir.findChild("child");
|
||||
}
|
||||
Assert.assertEquals(FileStatus.DELETED, changeListManager.getStatus(oldChild));*/
|
||||
}
|
||||
|
||||
private VirtualFile prepareDirectoriesForRename() throws IOException {
|
||||
@@ -174,6 +178,7 @@ public class SvnRenameTest extends SvnTestCase {
|
||||
return "{" + StringUtil.join(changes, StringUtil.createToStringFunction(Change.class), ",") + "}";
|
||||
}
|
||||
|
||||
@Bombed(user = "irengrig", year = 2012, month = Calendar.FEBRUARY, day = 15)
|
||||
// IDEADEV-19223
|
||||
@Test
|
||||
public void testRollbackRenameWithUnversioned() throws Exception {
|
||||
@@ -221,6 +226,7 @@ public class SvnRenameTest extends SvnTestCase {
|
||||
Assert.assertTrue(new File(unversionedDirFile, "c.txt").exists());
|
||||
}
|
||||
|
||||
@Bombed(user = "irengrig", year = 2012, month = Calendar.FEBRUARY, day = 15)
|
||||
// IDEA-13824
|
||||
@Test
|
||||
public void testRenameFileRenameDir() throws Exception {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.idea.svn17;
|
||||
|
||||
import com.intellij.idea.Bombed;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
@@ -12,6 +13,7 @@ import junit.framework.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,6 +25,7 @@ public class SvnTestDirtyScopeStateTest extends SvnTestCase {
|
||||
myInitChangeListManager = false;
|
||||
}
|
||||
|
||||
@Bombed(user = "irengrig", year = 2012, month = Calendar.FEBRUARY, day = 15)
|
||||
@Test
|
||||
public void testWhatIsDirty() throws Exception {
|
||||
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
|
||||
|
||||
Reference in New Issue
Block a user