mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -71,9 +71,9 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.jps.api.BasicFuture;
|
||||
import org.jetbrains.jps.api.CmdlineProtoUtil;
|
||||
import org.jetbrains.jps.api.CmdlineRemoteProto;
|
||||
import org.jetbrains.jps.api.TaskFuture;
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -138,7 +138,7 @@ public class CompileDriver {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final BasicFuture future = compileInExternalProcess(compileContext, true);
|
||||
final TaskFuture future = compileInExternalProcess(compileContext, true);
|
||||
if (future != null) {
|
||||
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
|
||||
if (indicator.isCanceled()) {
|
||||
@@ -194,7 +194,7 @@ public class CompileDriver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private BasicFuture compileInExternalProcess(final @NotNull CompileContextImpl compileContext, final boolean onlyCheckUpToDate)
|
||||
private TaskFuture compileInExternalProcess(final @NotNull CompileContextImpl compileContext, final boolean onlyCheckUpToDate)
|
||||
throws Exception {
|
||||
final CompileScope scope = compileContext.getCompileScope();
|
||||
final Collection<String> paths = CompileScopeUtil.fetchFiles(compileContext);
|
||||
@@ -400,7 +400,7 @@ public class CompileDriver {
|
||||
return;
|
||||
}
|
||||
|
||||
final BasicFuture future = compileInExternalProcess(compileContext, false);
|
||||
final TaskFuture future = compileInExternalProcess(compileContext, false);
|
||||
if (future != null) {
|
||||
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
|
||||
if (indicator.isCanceled()) {
|
||||
|
||||
@@ -100,7 +100,8 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap;
|
||||
import org.jetbrains.jps.incremental.Utils;
|
||||
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
|
||||
|
||||
import javax.tools.*;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -108,8 +109,7 @@ import java.net.InetSocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
|
||||
@@ -148,10 +148,10 @@ public class BuildManager implements ApplicationComponent{
|
||||
private final File mySystemDirectory;
|
||||
private final ProjectManager myProjectManager;
|
||||
|
||||
private final Map<BasicFuture, Project> myAutomakeFutures = Collections.synchronizedMap(new HashMap<BasicFuture, Project>());
|
||||
private final Map<TaskFuture, Project> myAutomakeFutures = Collections.synchronizedMap(new HashMap<TaskFuture, Project>());
|
||||
private final Map<String, RequestFuture> myBuildsInProgress = Collections.synchronizedMap(new HashMap<String, RequestFuture>());
|
||||
private final Map<String, Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> myPreloadedBuilds =
|
||||
Collections.synchronizedMap(new HashMap<String, Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>());
|
||||
private final Map<String, Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>> myPreloadedBuilds =
|
||||
Collections.synchronizedMap(new HashMap<String, Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>>());
|
||||
private final BuildProcessClasspathManager myClasspathManager = new BuildProcessClasspathManager();
|
||||
private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
|
||||
private final Map<String, ProjectData> myProjectDataMap = Collections.synchronizedMap(new HashMap<String, ProjectData>());
|
||||
@@ -447,7 +447,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
final List<TargetTypeBuildScope> scopes = CmdlineProtoUtil.createAllModulesScopes(false);
|
||||
final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project);
|
||||
final BasicFuture future = scheduleBuild(
|
||||
final TaskFuture future = scheduleBuild(
|
||||
project, false, true, false, scopes, Collections.<String>emptyList(), Collections.<String, String>emptyMap(), handler
|
||||
);
|
||||
if (future != null) {
|
||||
@@ -526,12 +526,12 @@ public class BuildManager implements ApplicationComponent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Collection<BasicFuture> cancelAutoMakeTasks(Project project) {
|
||||
final Collection<BasicFuture> futures = new SmartList<BasicFuture>();
|
||||
public Collection<TaskFuture> cancelAutoMakeTasks(Project project) {
|
||||
final Collection<TaskFuture> futures = new SmartList<TaskFuture>();
|
||||
synchronized (myAutomakeFutures) {
|
||||
for (Map.Entry<BasicFuture, Project> entry : myAutomakeFutures.entrySet()) {
|
||||
for (Map.Entry<TaskFuture, Project> entry : myAutomakeFutures.entrySet()) {
|
||||
if (entry.getValue().equals(project)) {
|
||||
final BasicFuture future = entry.getKey();
|
||||
final TaskFuture future = entry.getKey();
|
||||
future.cancel(false);
|
||||
futures.add(future);
|
||||
}
|
||||
@@ -542,15 +542,15 @@ public class BuildManager implements ApplicationComponent{
|
||||
|
||||
private void cancelPreloadedBuilds(Project project) {
|
||||
final String projectPath = getProjectPath(project);
|
||||
final Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> pair = myPreloadedBuilds.remove(projectPath);
|
||||
if (pair != null) {
|
||||
final RequestFuture<PreloadedProcessMessageHandler> future = pair.first;
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> pair = takePreloadedProcess(projectPath);
|
||||
if (pair != null) {
|
||||
final RequestFuture<PreloadedProcessMessageHandler> future = pair.first;
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
// waiting for preloaded process from project's task queue guarantees no build is started for this project
|
||||
// until this one gracefully exits and closes all its storages
|
||||
// until this one gracefully exits and closes all its storages
|
||||
getProjectData(projectPath).taskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -558,207 +558,221 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BasicFuture scheduleBuild(
|
||||
private Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> takePreloadedProcess(String projectPath) {
|
||||
Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> result;
|
||||
final Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> preloadProgress = myPreloadedBuilds.remove(projectPath);
|
||||
try {
|
||||
result = preloadProgress != null ? preloadProgress.get() : null;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.info(e);
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TaskFuture scheduleBuild(
|
||||
final Project project, final boolean isRebuild, final boolean isMake,
|
||||
final boolean onlyCheckUpToDate, final List<TargetTypeBuildScope> scopes,
|
||||
final Collection<String> paths,
|
||||
final Map<String, String> userData, final DefaultMessageHandler messageHandler) {
|
||||
|
||||
final String projectPath = getProjectPath(project);
|
||||
|
||||
final Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> preloaded = myPreloadedBuilds.remove(projectPath);
|
||||
final RequestFuture<PreloadedProcessMessageHandler> preloadedFuture = preloaded != null? preloaded.first : null;
|
||||
final boolean usingPreloadedProcess = preloadedFuture != null;
|
||||
|
||||
final UUID sessionId;
|
||||
final BuilderMessageHandler handler = new NotifyingMessageHandler(project, messageHandler, messageHandler instanceof AutoMakeMessageHandler);
|
||||
if (usingPreloadedProcess) {
|
||||
LOG.info("Using preloaded build process to compile " + projectPath);
|
||||
sessionId = preloadedFuture.getRequestID();
|
||||
preloadedFuture.getMessageHandler().setDelegateHandler(handler);
|
||||
}
|
||||
else {
|
||||
sessionId = UUID.randomUUID();
|
||||
}
|
||||
|
||||
try {
|
||||
ensureListening();
|
||||
}
|
||||
catch (Exception e) {
|
||||
final UUID sessionId = UUID.randomUUID(); // the actual session did not start, use random UUID
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
|
||||
handler.sessionTerminated(sessionId);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final RequestFuture<? extends BuilderMessageHandler> future = usingPreloadedProcess? preloadedFuture : new RequestFuture<BuilderMessageHandler>(handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
final DelegateFuture<BuilderMessageHandler> _future = new DelegateFuture<BuilderMessageHandler>();
|
||||
// by using the same queue that processes events we ensure that
|
||||
// the build will be aware of all events that have happened before this request
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
final Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> preloaded = takePreloadedProcess(projectPath);
|
||||
final RequestFuture<PreloadedProcessMessageHandler> preloadedFuture = preloaded != null? preloaded.first : null;
|
||||
final boolean usingPreloadedProcess = preloadedFuture != null;
|
||||
|
||||
final UUID sessionId;
|
||||
if (usingPreloadedProcess) {
|
||||
LOG.info("Using preloaded build process to compile " + projectPath);
|
||||
sessionId = preloadedFuture.getRequestID();
|
||||
preloadedFuture.getMessageHandler().setDelegateHandler(handler);
|
||||
}
|
||||
else {
|
||||
sessionId = UUID.randomUUID();
|
||||
}
|
||||
});
|
||||
// by using the same queue that processes events we ensure that
|
||||
// the build will be aware of all events that have happened before this request
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!usingPreloadedProcess && (future.isCancelled() || project.isDisposed())) {
|
||||
// in case of preloaded process the process was already running, so the handler will be notified upon process termination
|
||||
handler.sessionTerminated(sessionId);
|
||||
future.setDone();
|
||||
return;
|
||||
}
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals =
|
||||
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder().setGlobalOptionsPath(PathManager.getOptionsPath()).build();
|
||||
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges;
|
||||
final SequentialTaskExecutor projectTaskQueue;
|
||||
synchronized (myProjectDataMap) {
|
||||
final ProjectData data = getProjectData(projectPath);
|
||||
if (isRebuild) {
|
||||
data.dropChanges();
|
||||
}
|
||||
if (IS_UNIT_TEST_MODE) {
|
||||
LOG.info("Scheduling build for " +
|
||||
projectPath +
|
||||
"; CHANGED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myChanged)) +
|
||||
"; DELETED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myDeleted)));
|
||||
}
|
||||
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
|
||||
projectTaskQueue = data.taskQueue;
|
||||
final RequestFuture<? extends BuilderMessageHandler> future = usingPreloadedProcess? preloadedFuture : new RequestFuture<BuilderMessageHandler>(handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
});
|
||||
_future.setDelegate(future);
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage params;
|
||||
if (!usingPreloadedProcess && (future.isCancelled() || project.isDisposed())) {
|
||||
// in case of preloaded process the process was already running, so the handler will be notified upon process termination
|
||||
handler.sessionTerminated(sessionId);
|
||||
((BasicFuture)future).setDone();
|
||||
return;
|
||||
}
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals =
|
||||
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder().setGlobalOptionsPath(PathManager.getOptionsPath()).build();
|
||||
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges;
|
||||
final SequentialTaskExecutor projectTaskQueue;
|
||||
synchronized (myProjectDataMap) {
|
||||
final ProjectData data = getProjectData(projectPath);
|
||||
if (isRebuild) {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, Collections.<String>emptyList(), userData, globals, null);
|
||||
data.dropChanges();
|
||||
}
|
||||
else if (onlyCheckUpToDate) {
|
||||
params = CmdlineProtoUtil.createUpToDateCheckRequest(projectPath, scopes, paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
else {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, isMake ? Collections.<String>emptyList() : paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
if (!usingPreloadedProcess) {
|
||||
myMessageDispatcher.registerBuildMessageHandler(future, params);
|
||||
if (IS_UNIT_TEST_MODE) {
|
||||
LOG.info("Scheduling build for " +
|
||||
projectPath +
|
||||
"; CHANGED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myChanged)) +
|
||||
"; DELETED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myDeleted)));
|
||||
}
|
||||
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
|
||||
projectTaskQueue = data.taskQueue;
|
||||
}
|
||||
|
||||
try {
|
||||
projectTaskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Throwable execFailure = null;
|
||||
try {
|
||||
if (project.isDisposed()) {
|
||||
if (usingPreloadedProcess) {
|
||||
future.cancel(true);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
myBuildsInProgress.put(projectPath, future);
|
||||
final OSProcessHandler processHandler;
|
||||
final StringBuilder errorsOnLaunch = new StringBuilder();
|
||||
final CmdlineRemoteProto.Message.ControllerMessage params;
|
||||
if (isRebuild) {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, Collections.<String>emptyList(), userData, globals, null);
|
||||
}
|
||||
else if (onlyCheckUpToDate) {
|
||||
params = CmdlineProtoUtil.createUpToDateCheckRequest(projectPath, scopes, paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
else {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, isMake ? Collections.<String>emptyList() : paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
if (!usingPreloadedProcess) {
|
||||
myMessageDispatcher.registerBuildMessageHandler(future, params);
|
||||
}
|
||||
|
||||
try {
|
||||
projectTaskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Throwable execFailure = null;
|
||||
try {
|
||||
if (project.isDisposed()) {
|
||||
if (usingPreloadedProcess) {
|
||||
final boolean paramsSent = myMessageDispatcher.sendBuildParameters(future.getRequestID(), params);
|
||||
if (!paramsSent) {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
processHandler = preloaded.second;
|
||||
future.cancel(true);
|
||||
}
|
||||
else {
|
||||
processHandler = launchBuildProcess(project, myListenPort, sessionId, false);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
if (errorsOnLaunch.length() < 1024) {
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
errorsOnLaunch.append(text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
myBuildsInProgress.put(projectPath, future);
|
||||
final OSProcessHandler processHandler;
|
||||
final StringBuilder errorsOnLaunch = new StringBuilder();
|
||||
if (usingPreloadedProcess) {
|
||||
final boolean paramsSent = myMessageDispatcher.sendBuildParameters(future.getRequestID(), params);
|
||||
if (!paramsSent) {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
processHandler = preloaded.second;
|
||||
}
|
||||
else {
|
||||
processHandler = launchBuildProcess(project, myListenPort, sessionId, false);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
if (errorsOnLaunch.length() < 1024) {
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
errorsOnLaunch.append(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
processHandler.startNotify();
|
||||
}
|
||||
|
||||
final boolean terminated = processHandler.waitFor();
|
||||
if (terminated) {
|
||||
final int exitValue = processHandler.getProcess().exitValue();
|
||||
if (exitValue != 0) {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("Abnormal build process termination: ");
|
||||
if (errorsOnLaunch.length() > 0) {
|
||||
msg.append("\n").append(errorsOnLaunch);
|
||||
}
|
||||
else {
|
||||
msg.append("unknown error");
|
||||
}
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
|
||||
}
|
||||
}
|
||||
else {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
|
||||
});
|
||||
processHandler.startNotify();
|
||||
}
|
||||
|
||||
final boolean terminated = processHandler.waitFor();
|
||||
if (terminated) {
|
||||
final int exitValue = processHandler.getProcess().exitValue();
|
||||
if (exitValue != 0) {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("Abnormal build process termination: ");
|
||||
if (errorsOnLaunch.length() > 0) {
|
||||
msg.append("\n").append(errorsOnLaunch);
|
||||
}
|
||||
else {
|
||||
msg.append("unknown error");
|
||||
}
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
execFailure = e;
|
||||
}
|
||||
finally {
|
||||
myBuildsInProgress.remove(projectPath);
|
||||
if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) {
|
||||
// either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process.
|
||||
// in this case the session cannot be unregistered by the message dispatcher
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
if (execFailure != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure));
|
||||
}
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Registry.is("compiler.process.preload") && !project.isDisposed()) {
|
||||
try {
|
||||
final Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> pair = launchPreloadedBuildProcess(project);
|
||||
myPreloadedBuilds.put(projectPath, pair);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("Error pre-loading build process for project " + projectPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
catch (Throwable e) {
|
||||
execFailure = e;
|
||||
}
|
||||
finally {
|
||||
myBuildsInProgress.remove(projectPath);
|
||||
if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) {
|
||||
// either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process.
|
||||
// in this case the session cannot be unregistered by the message dispatcher
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
if (execFailure != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure));
|
||||
}
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Registry.is("compiler.process.preload") && !project.isDisposed()) {
|
||||
runCommand(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> preloadResult = launchPreloadedBuildProcess(project, projectTaskQueue);
|
||||
myPreloadedBuilds.put(projectPath, preloadResult);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("Error pre-loading build process for project " + projectPath, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
handler.sessionTerminated(sessionId);
|
||||
}
|
||||
|
||||
return null;
|
||||
return _future;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -798,37 +812,42 @@ public class BuildManager implements ApplicationComponent{
|
||||
return "com.intellij.compiler.server.BuildManager";
|
||||
}
|
||||
|
||||
private Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> launchPreloadedBuildProcess(final Project project) throws Exception {
|
||||
private Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception {
|
||||
ensureListening();
|
||||
|
||||
final RequestFuture<PreloadedProcessMessageHandler> future = new RequestFuture<PreloadedProcessMessageHandler>(new PreloadedProcessMessageHandler(project), UUID.randomUUID(), new RequestFuture.CancelAction<PreloadedProcessMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<PreloadedProcessMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
// launching build process from projectTaskQueue ensures that no other build process for this project is currently running
|
||||
return projectTaskQueue.submit(new Callable<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>() {
|
||||
public Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> call() throws Exception {
|
||||
final RequestFuture<PreloadedProcessMessageHandler> future = new RequestFuture<PreloadedProcessMessageHandler>(new PreloadedProcessMessageHandler(project), UUID.randomUUID(), new RequestFuture.CancelAction<PreloadedProcessMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<PreloadedProcessMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
});
|
||||
try {
|
||||
myMessageDispatcher.registerBuildMessageHandler(future, null);
|
||||
final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, future.getRequestID(), true);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
LOG.info("PRELOADED_BUILD_PROCESS: " + text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
processHandler.startNotify();
|
||||
return Pair.create(future, processHandler);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
myMessageDispatcher.unregisterBuildMessageHandler(future.getRequestID());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
myMessageDispatcher.registerBuildMessageHandler(future, null);
|
||||
try {
|
||||
final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, future.getRequestID(), true);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
LOG.info("PRELOADED_BUILD_PROCESS: " + text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
processHandler.startNotify();
|
||||
return Pair.create(future, processHandler);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
myMessageDispatcher.unregisterBuildMessageHandler(future.getRequestID());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId, boolean requestProjectPreload) throws ExecutionException {
|
||||
@@ -1300,7 +1319,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
@Override
|
||||
public void projectClosing(Project project) {
|
||||
cancelPreloadedBuilds(project);
|
||||
for (BasicFuture future : cancelAutoMakeTasks(project)) {
|
||||
for (TaskFuture future : cancelAutoMakeTasks(project)) {
|
||||
future.waitFor(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -1460,5 +1479,88 @@ public class BuildManager implements ApplicationComponent{
|
||||
return "/";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class DelegateFuture<T> implements TaskFuture<T> {
|
||||
@Nullable
|
||||
private TaskFuture<? extends T> myDelegate;
|
||||
private Boolean myRequestedCancelState = null;
|
||||
|
||||
@NotNull
|
||||
public synchronized TaskFuture<? extends T> getDelegate() {
|
||||
TaskFuture<? extends T> delegate = myDelegate;
|
||||
while (delegate == null) {
|
||||
try {
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
delegate = myDelegate;
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public synchronized boolean setDelegate(@NotNull TaskFuture<? extends T> delegate) {
|
||||
if (myDelegate == null) {
|
||||
try {
|
||||
myDelegate = delegate;
|
||||
if (myRequestedCancelState != null) {
|
||||
myDelegate.cancel(myRequestedCancelState);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
notifyAll();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized boolean cancel(boolean mayInterruptIfRunning) {
|
||||
final TaskFuture<? extends T> delegate = myDelegate;
|
||||
if (delegate == null) {
|
||||
myRequestedCancelState = mayInterruptIfRunning;
|
||||
return true;
|
||||
}
|
||||
return delegate.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
|
||||
public void waitFor() {
|
||||
getDelegate().waitFor();
|
||||
}
|
||||
|
||||
public boolean waitFor(long timeout, TimeUnit unit) {
|
||||
return getDelegate().waitFor(timeout, unit);
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
final TaskFuture<? extends T> delegate;
|
||||
synchronized (this) {
|
||||
delegate = myDelegate;
|
||||
if (delegate == null) {
|
||||
return myRequestedCancelState != null;
|
||||
}
|
||||
}
|
||||
return delegate.isCancelled();
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
final TaskFuture<? extends T> delegate;
|
||||
synchronized (this) {
|
||||
delegate = myDelegate;
|
||||
if (delegate == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return delegate.isDone();
|
||||
}
|
||||
|
||||
public T get() throws InterruptedException, java.util.concurrent.ExecutionException {
|
||||
return getDelegate().get();
|
||||
}
|
||||
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, java.util.concurrent.ExecutionException, TimeoutException {
|
||||
return getDelegate().get(timeout, unit);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
}
|
||||
|
||||
public JavaReferringObjectsValue(@NotNull JavaValue javaValue, boolean isField) {
|
||||
super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), null, false);
|
||||
super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), javaValue.getNodeManager(), false);
|
||||
myIsField = isField;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
return reference;
|
||||
}
|
||||
};
|
||||
children.add(new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, true));
|
||||
children.add(new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), getNodeManager(), true));
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
@@ -109,7 +109,7 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
children.add("Referrer " + i++, new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, false));
|
||||
children.add("Referrer " + i++, new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), getNodeManager(), false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,4 +168,10 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public XValueModifier getModifier() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
private final EvaluationContextImpl myEvaluationContext;
|
||||
private final NodeManagerImpl myNodeManager;
|
||||
private final boolean myContextSet;
|
||||
private final DebuggerManagerThreadImpl myDebuggerManagerThread;
|
||||
|
||||
protected JavaValue(JavaValue parent,
|
||||
@NotNull ValueDescriptorImpl valueDescriptor,
|
||||
@@ -82,6 +83,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
myEvaluationContext = evaluationContext;
|
||||
myNodeManager = nodeManager;
|
||||
myContextSet = contextSet;
|
||||
myDebuggerManagerThread = evaluationContext.getDebugProcess().getManagerThread();
|
||||
}
|
||||
|
||||
static JavaValue create(JavaValue parent,
|
||||
@@ -113,6 +115,10 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
return myEvaluationContext;
|
||||
}
|
||||
|
||||
public NodeManagerImpl getNodeManager() {
|
||||
return myNodeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computePresentation(@NotNull final XValueNode node, @NotNull XValuePlace place) {
|
||||
final SuspendContextImpl suspendContext = myEvaluationContext.getSuspendContext();
|
||||
@@ -349,7 +355,11 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
}
|
||||
|
||||
boolean scheduleCommand(SuspendContextCommandImpl command) {
|
||||
return scheduleCommand(myEvaluationContext, null, command);
|
||||
if (myEvaluationContext.getSuspendContext().isResumed()) {
|
||||
return false;
|
||||
}
|
||||
myDebuggerManagerThread.schedule(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static boolean scheduleCommand(EvaluationContextImpl evaluationContext,
|
||||
@@ -486,6 +496,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
@Nullable
|
||||
@Override
|
||||
public XReferrersProvider getReferrersProvider() {
|
||||
if (myEvaluationContext.getSuspendContext().isResumed()) return null;
|
||||
return new XReferrersProvider() {
|
||||
@Override
|
||||
public XValue getReferringObjectsValue() {
|
||||
@@ -497,16 +508,15 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
@Nullable
|
||||
@Override
|
||||
public XInstanceEvaluator getInstanceEvaluator() {
|
||||
final DebugProcessImpl process = myEvaluationContext.getDebugProcess();
|
||||
return new XInstanceEvaluator() {
|
||||
@Override
|
||||
public void evaluate(@NotNull final XDebuggerEvaluator.XEvaluationCallback callback, @NotNull final XStackFrame frame) {
|
||||
process.getManagerThread().schedule(new DebuggerCommandImpl() {
|
||||
myDebuggerManagerThread.schedule(new DebuggerCommandImpl() {
|
||||
@Override
|
||||
protected void action() throws Exception {
|
||||
ValueDescriptorImpl inspectDescriptor = myValueDescriptor;
|
||||
if (myValueDescriptor instanceof WatchItemDescriptor) {
|
||||
inspectDescriptor = (ValueDescriptorImpl) ((WatchItemDescriptor) myValueDescriptor).getModifier().getInspectItem(getProject());
|
||||
inspectDescriptor = (ValueDescriptorImpl)((WatchItemDescriptor)myValueDescriptor).getModifier().getInspectItem(getProject());
|
||||
}
|
||||
EvaluationContextImpl evaluationContext = ((JavaStackFrame)frame).getFrameDebuggerContext().createEvaluationContext();
|
||||
if (evaluationContext != null) {
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
*/
|
||||
package org.jetbrains.jps.api;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 5/3/12
|
||||
*/
|
||||
public class BasicFuture<T> implements Future<T> {
|
||||
public class BasicFuture<T> implements TaskFuture<T> {
|
||||
protected final Semaphore mySemaphore = new Semaphore(1);
|
||||
private final AtomicBoolean myDone = new AtomicBoolean(false);
|
||||
private final AtomicBoolean myCanceledState = new AtomicBoolean(false);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.jps.api;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public interface TaskFuture<T> extends Future<T> {
|
||||
void waitFor();
|
||||
|
||||
boolean waitFor(long timeout, TimeUnit unit);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.jps.cmdline;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
@@ -124,9 +125,12 @@ public class BuildMain {
|
||||
final String projectPathToPreload = System.getProperty(PRELOAD_PROJECT_PATH, null);
|
||||
final String globalsPathToPreload = System.getProperty(PRELOAD_CONFIG_PATH, null);
|
||||
if (projectPathToPreload != null && globalsPathToPreload != null) {
|
||||
final long preloadStart = System.currentTimeMillis();
|
||||
final PreloadedData data = new PreloadedData();
|
||||
ourPreloadedData = data;
|
||||
try {
|
||||
FileSystemUtil.getAttributes(projectPathToPreload); // this will pre-load all FS optimizations
|
||||
|
||||
final BuildRunner runner = new BuildRunner(new JpsModelLoaderImpl(projectPathToPreload, globalsPathToPreload, null));
|
||||
data.setRunner(runner);
|
||||
|
||||
@@ -162,10 +166,11 @@ public class BuildMain {
|
||||
LOG.info("Error pre-loading FS state", e);
|
||||
fsState.clearAll();
|
||||
}
|
||||
LOG.info("Pre-loaded project model in " + (System.currentTimeMillis() - preloadStart) + " ms");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.info("Failed to pre-load project " + projectPathToPreload, e);
|
||||
// just failed to preload the project, the situation will be handled later, when real build starts
|
||||
// just failed to preload the project, the situation will be handled later, when real build starts
|
||||
}
|
||||
}
|
||||
else if (projectPathToPreload != null || globalsPathToPreload != null){
|
||||
|
||||
@@ -168,7 +168,16 @@ public class JavacMain {
|
||||
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage()));
|
||||
}
|
||||
catch (CompilationCanceledException ignored) {
|
||||
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled"));
|
||||
handleCancelException(diagnosticConsumer);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof CompilationCanceledException) {
|
||||
handleCancelException(diagnosticConsumer);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
fileManager.close();
|
||||
@@ -179,6 +188,10 @@ public class JavacMain {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void handleCancelException(DiagnosticOutputConsumer diagnosticConsumer) {
|
||||
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled"));
|
||||
}
|
||||
|
||||
private static List<JavaSourceTransformer> getSourceTransformers() {
|
||||
final Class<JavaSourceTransformer> transformerClass = JavaSourceTransformer.class;
|
||||
final ServiceLoader<JavaSourceTransformer> loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader());
|
||||
|
||||
+22
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.jps.model.serialization;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
@@ -30,6 +31,8 @@ import java.io.IOException;
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class JpsLoaderBase {
|
||||
private static final Logger LOG = Logger.getInstance(JpsLoaderBase.class);
|
||||
private static final int MAX_ATTEMPTS = 5;
|
||||
private final JpsMacroExpander myMacroExpander;
|
||||
|
||||
protected JpsLoaderBase(JpsMacroExpander macroExpander) {
|
||||
@@ -66,7 +69,7 @@ public abstract class JpsLoaderBase {
|
||||
|
||||
protected static Element loadRootElement(final File file, final JpsMacroExpander macroExpander) {
|
||||
try {
|
||||
final Element element = JDOMUtil.loadDocument(file).getRootElement();
|
||||
final Element element = tryLoadRootElement(file);
|
||||
macroExpander.substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
return element;
|
||||
}
|
||||
@@ -78,6 +81,24 @@ public abstract class JpsLoaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static Element tryLoadRootElement(File file) throws IOException, JDOMException {
|
||||
for (int i = 0; i < MAX_ATTEMPTS - 1; i++) {
|
||||
try {
|
||||
return JDOMUtil.loadDocument(file).getRootElement();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("Loading attempt #" + i + " failed", e);
|
||||
}
|
||||
//most likely configuration file is being written by IDE so we'll wait a little
|
||||
try {
|
||||
//noinspection BusyWait
|
||||
Thread.sleep(300);
|
||||
}
|
||||
catch (InterruptedException ignored) { }
|
||||
}
|
||||
return JDOMUtil.loadDocument(file).getRootElement();
|
||||
}
|
||||
|
||||
protected static boolean isXmlFile(File file) {
|
||||
return file.isFile() && FileUtilRt.extensionEquals(file.getName(), "xml");
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
private final ASTNode myOriginalTree;
|
||||
private final MyTreeStructure myParentLightTree;
|
||||
private final int myOffset;
|
||||
|
||||
private static TokenSet ourAnyLanguageWhitespaceTokens = TokenSet.EMPTY;
|
||||
|
||||
@@ -132,7 +133,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree) {
|
||||
this(project, containingFile, parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, charTable, text,
|
||||
originalTree, parentLightTree);
|
||||
originalTree, parentLightTree, 0);
|
||||
}
|
||||
|
||||
public PsiBuilderImpl(Project project,
|
||||
@@ -144,6 +145,19 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final CharSequence text,
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree) {
|
||||
this(project, containingFile, whiteSpaces, comments, lexer, charTable, text, originalTree, parentLightTree, 0);
|
||||
}
|
||||
|
||||
private PsiBuilderImpl(Project project,
|
||||
PsiFile containingFile,
|
||||
@NotNull TokenSet whiteSpaces,
|
||||
@NotNull TokenSet comments,
|
||||
@NotNull Lexer lexer,
|
||||
CharTable charTable,
|
||||
@NotNull final CharSequence text,
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree,
|
||||
int offset) {
|
||||
myProject = project;
|
||||
myFile = containingFile;
|
||||
|
||||
@@ -156,6 +170,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
myCharTable = charTable;
|
||||
myOriginalTree = originalTree;
|
||||
myParentLightTree = parentLightTree;
|
||||
myOffset = offset;
|
||||
|
||||
cacheLexemes();
|
||||
}
|
||||
@@ -174,8 +189,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final Lexer lexer,
|
||||
@NotNull final LighterLazyParseableNode chameleon,
|
||||
@NotNull final CharSequence text) {
|
||||
this(project, chameleon.getContainingFile(), parserDefinition, lexer, chameleon.getCharTable(), text,
|
||||
null, ((LazyParseableToken)chameleon).myParent);
|
||||
this(project, chameleon.getContainingFile(), parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer,
|
||||
chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent, chameleon.getStartOffset());
|
||||
}
|
||||
|
||||
private void cacheLexemes() {
|
||||
@@ -335,12 +350,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
@Override
|
||||
public int getStartOffset() {
|
||||
return myBuilder.myLexStarts[myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndOffset() {
|
||||
return myBuilder.myLexStarts[myDoneMarker.myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myDoneMarker.myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -487,12 +502,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
@Override
|
||||
public int getEndOffset() {
|
||||
return myTokenEnd;
|
||||
return myTokenEnd + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartOffset() {
|
||||
return myTokenStart;
|
||||
return myTokenStart + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
public CharSequence getText() {
|
||||
@@ -636,12 +651,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
@Override
|
||||
public int getEndOffset() {
|
||||
return myBuilder.myLexStarts[myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartOffset() {
|
||||
return myBuilder.myLexStarts[myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1474,6 +1489,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
private final LimitedPool<Token> myPool;
|
||||
private final LimitedPool<LazyParseableToken> myLazyPool;
|
||||
private final StartMarker myRoot;
|
||||
private final int myOffset;
|
||||
|
||||
public MyTreeStructure(@NotNull StartMarker root, @Nullable final MyTreeStructure parentTree) {
|
||||
if (parentTree == null) {
|
||||
@@ -1499,10 +1515,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
return new LazyParseableToken();
|
||||
}
|
||||
});
|
||||
myOffset = 0;
|
||||
}
|
||||
else {
|
||||
myPool = parentTree.myPool;
|
||||
myLazyPool = parentTree.myLazyPool;
|
||||
myOffset = parentTree.getRoot().getStartOffset();
|
||||
}
|
||||
myRoot = root;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ import java.util.Map;
|
||||
public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayList> implements PsiDependentIndex {
|
||||
static boolean ourEnabled = SystemProperties.getBooleanProperty("idea.enable.duplicates.online.calculation",
|
||||
isEnabledByDefault());
|
||||
static boolean ourEnabledLightProfiles = false;
|
||||
static boolean ourEnabledLightProfiles = true;
|
||||
|
||||
private static boolean isEnabledByDefault() {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
|
||||
+176
-67
@@ -3,10 +3,16 @@ package com.intellij.dupLocator.index;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.dupLocator.DuplicatesProfile;
|
||||
import com.intellij.dupLocator.DuplocatorState;
|
||||
import com.intellij.dupLocator.LightDuplicateProfile;
|
||||
import com.intellij.dupLocator.treeHash.FragmentsCollector;
|
||||
import com.intellij.dupLocator.util.PsiFragment;
|
||||
import com.intellij.lang.LighterAST;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.lang.TreeBackedLighterAST;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
@@ -35,94 +41,126 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
final DuplicatesProfile profile = DuplicatesIndex.findDuplicatesProfile(psiFile.getFileType());
|
||||
if (profile == null) return ProblemDescriptor.EMPTY_ARRAY;
|
||||
|
||||
final DuplocatorState state = profile.getDuplocatorState(psiFile.getLanguage());
|
||||
final SmartList<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
|
||||
final Ref<DuplicatedCodeProcessor> myProcessorRef = new Ref<DuplicatedCodeProcessor>();
|
||||
|
||||
final TreeMap<Integer, TextRange> reportedRanges = new TreeMap<Integer, TextRange>();
|
||||
final TIntObjectHashMap<VirtualFile> reportedFiles = new TIntObjectHashMap<VirtualFile>();
|
||||
final TIntObjectHashMap<PsiElement> reportedPsi = new TIntObjectHashMap<PsiElement>();
|
||||
final TIntIntHashMap reportedOffsetInOtherFiles = new TIntIntHashMap();
|
||||
final TIntIntHashMap fragmentSize = new TIntIntHashMap();
|
||||
if (profile instanceof LightDuplicateProfile && DuplicatesIndex.ourEnabledLightProfiles) {
|
||||
|
||||
profile.createVisitor(new FragmentsCollector() {
|
||||
@Override
|
||||
public void add(int hash, final int cost, @Nullable final PsiFragment frag) {
|
||||
if (!DuplicatesIndex.isIndexedFragment(frag, cost, profile, state)) {
|
||||
return;
|
||||
((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() {
|
||||
DuplicatedCodeProcessor<LighterASTNode> myProcessor;
|
||||
@Override
|
||||
public void process(final LighterAST ast, final LighterASTNode node, int hash) {
|
||||
class LightDuplicatedCodeProcessor extends DuplicatedCodeProcessor<LighterASTNode> {
|
||||
|
||||
LightDuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
super(file, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextRange getRangeInElement(LighterASTNode node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement getPsi(LighterASTNode node) {
|
||||
return ((TreeBackedLighterAST)ast).unwrap(node).getPsi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getStartOffset(LighterASTNode node) {
|
||||
return node.getStartOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getEndOffset(LighterASTNode node) {
|
||||
return node.getEndOffset();
|
||||
}
|
||||
}
|
||||
if (myProcessor == null) {
|
||||
myProcessor = new LightDuplicatedCodeProcessor(virtualFile, psiFile.getProject());
|
||||
myProcessorRef.set(myProcessor);
|
||||
}
|
||||
myProcessor.process(hash, node);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final DuplocatorState state = profile.getDuplocatorState(psiFile.getLanguage());
|
||||
profile.createVisitor(new FragmentsCollector() {
|
||||
DuplicatedCodeProcessor<PsiFragment> myProcessor;
|
||||
@Override
|
||||
public void add(int hash, final int cost, @Nullable final PsiFragment frag) {
|
||||
if (!DuplicatesIndex.isIndexedFragment(frag, cost, profile, state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressManager.checkCanceled();
|
||||
FileBasedIndex.getInstance().processValues(DuplicatesIndex.NAME, hash, null, new FileBasedIndex.ValueProcessor<TIntArrayList>() {
|
||||
final ProjectFileIndex myProjectFileIndex = ProjectFileIndex.SERVICE.getInstance(psiFile.getProject());
|
||||
@Override
|
||||
public boolean process(final VirtualFile file, final TIntArrayList list) {
|
||||
for(int i = 0, len = list.size(); i < len; ++i) {
|
||||
ProgressManager.checkCanceled();
|
||||
class OldDuplicatedCodeProcessor extends DuplicatedCodeProcessor<PsiFragment> {
|
||||
|
||||
int value = list.getQuick(i);
|
||||
OldDuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
super(file, project);
|
||||
}
|
||||
|
||||
if (myProjectFileIndex.isInSource(virtualFile) && !myProjectFileIndex.isInSource(file)) return true;
|
||||
if (!myProjectFileIndex.isInSource(virtualFile) && myProjectFileIndex.isInSource(file)) return true;
|
||||
final int startOffset = frag.getStartOffset();
|
||||
final int endOffset = frag.getEndOffset();
|
||||
if (file.equals(virtualFile) && value >= startOffset && value < endOffset) continue;
|
||||
|
||||
PsiElement[] elements = frag.getElements();
|
||||
PsiElement target = elements[0];
|
||||
@Override
|
||||
protected TextRange getRangeInElement(PsiFragment node) {
|
||||
PsiElement[] elements = node.getElements();
|
||||
TextRange rangeInElement = null;
|
||||
if (elements.length > 1) {
|
||||
PsiElement firstElement = elements[0];
|
||||
target = firstElement.getParent();
|
||||
|
||||
PsiElement lastElement = elements[elements.length - 1];
|
||||
rangeInElement = new TextRange(
|
||||
elements[0].getStartOffsetInParent(),
|
||||
lastElement.getStartOffsetInParent() + lastElement.getTextLength()
|
||||
);
|
||||
}
|
||||
return rangeInElement;
|
||||
}
|
||||
|
||||
Integer fragmentStartOffsetInteger = startOffset;
|
||||
SortedMap<Integer,TextRange> map = reportedRanges.subMap(fragmentStartOffsetInteger, endOffset);
|
||||
int newFragmentSize = !map.isEmpty() ? 0:1;
|
||||
@Override
|
||||
protected PsiElement getPsi(PsiFragment node) {
|
||||
PsiElement[] elements = node.getElements();
|
||||
|
||||
Iterator<Integer> iterator = map.keySet().iterator();
|
||||
while(iterator.hasNext()) {
|
||||
Integer next = iterator.next();
|
||||
iterator.remove();
|
||||
reportedFiles.remove(next);
|
||||
reportedOffsetInOtherFiles.remove(next);
|
||||
reportedPsi.remove(next);
|
||||
newFragmentSize += fragmentSize.remove(next);
|
||||
}
|
||||
return elements.length > 1 ? elements[0].getParent() : elements[0];
|
||||
}
|
||||
|
||||
reportedRanges.put(fragmentStartOffsetInteger, rangeInElement);
|
||||
reportedFiles.put(fragmentStartOffsetInteger, file);
|
||||
reportedOffsetInOtherFiles.put(fragmentStartOffsetInteger, value);
|
||||
reportedPsi.put(fragmentStartOffsetInteger, target);
|
||||
fragmentSize.put(fragmentStartOffsetInteger, newFragmentSize);
|
||||
@Override
|
||||
protected int getStartOffset(PsiFragment node) {
|
||||
return node.getStartOffset();
|
||||
}
|
||||
|
||||
return false;
|
||||
@Override
|
||||
protected int getEndOffset(PsiFragment node) {
|
||||
return node.getEndOffset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, GlobalSearchScope.projectScope(psiFile.getProject()));
|
||||
if (myProcessor == null) {
|
||||
myProcessor = new OldDuplicatedCodeProcessor(virtualFile, psiFile.getProject());
|
||||
myProcessorRef.set(myProcessor);
|
||||
}
|
||||
myProcessor.process(hash, frag);
|
||||
}
|
||||
}, true).visitNode(psiFile);
|
||||
}
|
||||
|
||||
DuplicatedCodeProcessor<?> processor = myProcessorRef.get();
|
||||
|
||||
final SmartList<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
|
||||
|
||||
if (processor != null) {
|
||||
|
||||
for(Map.Entry<Integer, TextRange> entry:processor.reportedRanges.entrySet()) {
|
||||
final Integer offset = entry.getKey();
|
||||
// todo 3 statements constant
|
||||
if (processor.fragmentSize.get(offset) < 3) continue;
|
||||
final VirtualFile file = processor.reportedFiles.get(offset);
|
||||
String message = "Found duplicated code in " + file.getPath();
|
||||
|
||||
PsiElement targetElement = processor.reportedPsi.get(offset);
|
||||
TextRange rangeInElement = entry.getValue();
|
||||
final int offsetInOtherFile = processor.reportedOffsetInOtherFiles.get(offset);
|
||||
|
||||
LocalQuickFix fix = createNavigateToDupeFix(file, offsetInOtherFile);
|
||||
ProblemDescriptor descriptor = manager
|
||||
.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.WEAK_WARNING, isOnTheFly, fix);
|
||||
descriptors.add(descriptor);
|
||||
}
|
||||
}, true).visitNode(psiFile);
|
||||
|
||||
for(Map.Entry<Integer, TextRange> entry:reportedRanges.entrySet()) {
|
||||
final Integer offset = entry.getKey();
|
||||
// todo 3 statements constant
|
||||
if (fragmentSize.get(offset) < 3) continue;
|
||||
final VirtualFile file = reportedFiles.get(offset);
|
||||
String message = "Found duplicated code in " + file.getPath();
|
||||
|
||||
PsiElement targetElement = reportedPsi.get(offset);
|
||||
TextRange rangeInElement = entry.getValue();
|
||||
final int offsetInOtherFile = reportedOffsetInOtherFiles.get(offset);
|
||||
|
||||
LocalQuickFix fix = createNavigateToDupeFix(file, offsetInOtherFile);
|
||||
ProblemDescriptor descriptor = manager
|
||||
.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.WEAK_WARNING, isOnTheFly, fix);
|
||||
descriptors.add(descriptor);
|
||||
}
|
||||
|
||||
return descriptors.isEmpty() ? null : descriptors.toArray(new ProblemDescriptor[descriptors.size()]);
|
||||
@@ -131,4 +169,75 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
protected LocalQuickFix createNavigateToDupeFix(@NotNull VirtualFile file, int offsetInOtherFile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static abstract class DuplicatedCodeProcessor<T> implements FileBasedIndex.ValueProcessor<TIntArrayList> {
|
||||
final TreeMap<Integer, TextRange> reportedRanges = new TreeMap<Integer, TextRange>();
|
||||
final TIntObjectHashMap<VirtualFile> reportedFiles = new TIntObjectHashMap<VirtualFile>();
|
||||
final TIntObjectHashMap<PsiElement> reportedPsi = new TIntObjectHashMap<PsiElement>();
|
||||
final TIntIntHashMap reportedOffsetInOtherFiles = new TIntIntHashMap();
|
||||
final TIntIntHashMap fragmentSize = new TIntIntHashMap();
|
||||
final VirtualFile virtualFile;
|
||||
final Project project;
|
||||
final ProjectFileIndex myProjectFileIndex;
|
||||
T myNode;
|
||||
|
||||
DuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
virtualFile = file;
|
||||
this.project = project;
|
||||
myProjectFileIndex = ProjectFileIndex.SERVICE.getInstance(project);
|
||||
}
|
||||
|
||||
void process(int hash, T node) {
|
||||
ProgressManager.checkCanceled();
|
||||
myNode = node;
|
||||
FileBasedIndex.getInstance().processValues(DuplicatesIndex.NAME, hash, null, this, GlobalSearchScope.projectScope(project));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(VirtualFile file, TIntArrayList list) {
|
||||
for(int i = 0, len = list.size(); i < len; ++i) {
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
int value = list.getQuick(i);
|
||||
|
||||
if (myProjectFileIndex.isInSource(virtualFile) && !myProjectFileIndex.isInSource(file)) return true;
|
||||
if (!myProjectFileIndex.isInSource(virtualFile) && myProjectFileIndex.isInSource(file)) return true;
|
||||
final int startOffset = getStartOffset(myNode);
|
||||
final int endOffset = getEndOffset(myNode);
|
||||
if (file.equals(virtualFile) && value >= startOffset && value < endOffset) continue;
|
||||
|
||||
PsiElement target = getPsi(myNode);
|
||||
TextRange rangeInElement = getRangeInElement(myNode);
|
||||
|
||||
Integer fragmentStartOffsetInteger = startOffset;
|
||||
SortedMap<Integer,TextRange> map = reportedRanges.subMap(fragmentStartOffsetInteger, endOffset);
|
||||
int newFragmentSize = !map.isEmpty() ? 0:1;
|
||||
|
||||
Iterator<Integer> iterator = map.keySet().iterator();
|
||||
while(iterator.hasNext()) {
|
||||
Integer next = iterator.next();
|
||||
iterator.remove();
|
||||
reportedFiles.remove(next);
|
||||
reportedOffsetInOtherFiles.remove(next);
|
||||
reportedPsi.remove(next);
|
||||
newFragmentSize += fragmentSize.remove(next);
|
||||
}
|
||||
|
||||
reportedRanges.put(fragmentStartOffsetInteger, rangeInElement);
|
||||
reportedFiles.put(fragmentStartOffsetInteger, file);
|
||||
reportedOffsetInOtherFiles.put(fragmentStartOffsetInteger, value);
|
||||
reportedPsi.put(fragmentStartOffsetInteger, target);
|
||||
fragmentSize.put(fragmentStartOffsetInteger, newFragmentSize);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract TextRange getRangeInElement(T node);
|
||||
protected abstract PsiElement getPsi(T node);
|
||||
|
||||
protected abstract int getStartOffset(T node);
|
||||
protected abstract int getEndOffset(T node);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-6
@@ -358,8 +358,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
for (final StandardFileType pair : myStandardFileTypes.values()) {
|
||||
registerFileTypeWithoutNotification(pair.fileType, pair.matchers);
|
||||
}
|
||||
for (StandardFileType pair : myStandardFileTypes.values()) {
|
||||
registerReDetectedMappings(pair);
|
||||
if (!myUnresolvedMappings.isEmpty()) {
|
||||
for (StandardFileType pair : myStandardFileTypes.values()) {
|
||||
registerReDetectedMappings(pair);
|
||||
}
|
||||
}
|
||||
// Resolve unresolved mappings initialized before certain plugin initialized.
|
||||
for (final StandardFileType pair : myStandardFileTypes.values()) {
|
||||
@@ -1297,14 +1299,23 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
FileType fileType = pair.fileType;
|
||||
if (fileType == PlainTextFileType.INSTANCE) return;
|
||||
for (FileNameMatcher matcher : pair.matchers) {
|
||||
String typeName = myUnresolvedMappings.get(matcher);
|
||||
if (typeName != null && !typeName.equals(fileType.getName())) {
|
||||
Trinity<String, String, Boolean> trinity = myUnresolvedRemovedMappings.get(matcher);
|
||||
myRemovedMappings.put(matcher, Pair.create(fileType, trinity != null && trinity.third));
|
||||
registerReDetectedMapping(fileType, matcher);
|
||||
if (matcher instanceof ExtensionFileNameMatcher) {
|
||||
// also check exact file name matcher
|
||||
ExtensionFileNameMatcher extMatcher = (ExtensionFileNameMatcher)matcher;
|
||||
registerReDetectedMapping(fileType, new ExactFileNameMatcher("." + extMatcher.getExtension()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReDetectedMapping(@NotNull FileType fileType, @NotNull FileNameMatcher matcher) {
|
||||
String typeName = myUnresolvedMappings.get(matcher);
|
||||
if (typeName != null && !typeName.equals(fileType.getName())) {
|
||||
Trinity<String, String, Boolean> trinity = myUnresolvedRemovedMappings.get(matcher);
|
||||
myRemovedMappings.put(matcher, Pair.create(fileType, trinity != null && trinity.third));
|
||||
}
|
||||
}
|
||||
|
||||
Map<FileNameMatcher, Pair<FileType, Boolean>> getRemovedMappings() {
|
||||
return myRemovedMappings;
|
||||
}
|
||||
|
||||
@@ -38,14 +38,16 @@
|
||||
|
||||
<actions>
|
||||
<group id="RemoteServersViewToolbar">
|
||||
<action id="RemoteServers.RunServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RunServerAction"/>
|
||||
<action id="RemoteServers.DebugServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DebugServerAction"/>
|
||||
<action id="RemoteServers.StopServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.StopServerAction"/>
|
||||
<action id="RemoteServers.EditServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.EditConfigurationAction"/>
|
||||
<separator/>
|
||||
<action id="RemoteServers.DeployAll" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeployAllAction"/>
|
||||
<action id="RemoteServers.ConnectServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RemoteServerConnectAction"/>
|
||||
<action id="RemoteServers.DisconnectServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RemoteServerDisconnectAction"/>
|
||||
<action id="RemoteServers.EditServerConfig" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RemoteServerConfigAction"/>
|
||||
<action id="RemoteServers.ChooseServerDeployment" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.ChooseDeploymentAction"/>
|
||||
<action id="RemoteServers.ChooseServerDeploymentWithDebug" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.ChooseDeploymentWithDebugAction"/>
|
||||
|
||||
<action id="Servers.Deploy" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeployAction"/>
|
||||
<action id="Servers.Undeploy" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.UndeployAction"/>
|
||||
<action id="Servers.DeployWithDebug" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeployWithDebugAction"/>
|
||||
<action id="RemoteServers.EditDeploymentConfig" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeploymentConfigAction"/>
|
||||
</group>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
+6
-23
@@ -6,18 +6,16 @@ import com.intellij.ide.util.treeView.AbstractTreeNode;
|
||||
import com.intellij.ide.util.treeView.NodeDescriptor;
|
||||
import com.intellij.ide.util.treeView.NodeRenderer;
|
||||
import com.intellij.ide.util.treeView.TreeVisitor;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.remoteServer.configuration.RemoteServer;
|
||||
import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.TreeBuilderBase;
|
||||
import com.intellij.remoteServer.runtime.ConnectionStatus;
|
||||
import com.intellij.remoteServer.runtime.ServerConnection;
|
||||
@@ -108,13 +106,10 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
|
||||
new DoubleClickListener() {
|
||||
@Override
|
||||
protected boolean onDoubleClick(MouseEvent event) {
|
||||
Set<ServersTreeStructure.RemoteServerNode> nodes = getSelectedRemoteServerNodes();
|
||||
if (nodes.size() == 1) {
|
||||
RemoteServer<?> server = nodes.iterator().next().getValue();
|
||||
ServerConnectionManager.getInstance().getOrCreateConnection(server);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
AnAction connectAction = ActionManager.getInstance().getAction("RemoteServers.ConnectServer");
|
||||
AnActionEvent actionEvent = AnActionEvent.createFromInputEvent(connectAction, event, ActionPlaces.UNKNOWN);
|
||||
connectAction.actionPerformed(actionEvent);
|
||||
return true;
|
||||
}
|
||||
}.installOn(myTree);
|
||||
}
|
||||
@@ -265,18 +260,6 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Set<ServerNode> getSelectedServerNodes() {
|
||||
return myBuilder.getSelectedElements(ServerNode.class);
|
||||
}
|
||||
|
||||
public Set<DeploymentNode> getSelectedDeploymentNodes() {
|
||||
return myBuilder.getSelectedElements(DeploymentNode.class);
|
||||
}
|
||||
|
||||
public Set<ServersTreeStructure.RemoteServerNode> getSelectedRemoteServerNodes() {
|
||||
return myBuilder.getSelectedElements(ServersTreeStructure.RemoteServerNode.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
+11
-5
@@ -5,18 +5,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public interface DeploymentNode {
|
||||
public interface DeploymentNode extends ServersTreeNode {
|
||||
|
||||
@NotNull
|
||||
ServerNode getServerNode();
|
||||
|
||||
boolean isRedeployActionEnabled();
|
||||
void redeploy();
|
||||
boolean isDeployActionVisible();
|
||||
|
||||
boolean isDeployActionEnabled();
|
||||
|
||||
void deploy();
|
||||
|
||||
boolean isUndeployActionEnabled();
|
||||
|
||||
void undeploy();
|
||||
|
||||
boolean isEditConfigurationActionEnabled();
|
||||
void editConfiguration();
|
||||
boolean isDebugActionVisible();
|
||||
|
||||
void deployWithDebug();
|
||||
|
||||
boolean isDeployed();
|
||||
|
||||
|
||||
+1
-18
@@ -1,26 +1,9 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public interface ServerNode {
|
||||
boolean isConnected();
|
||||
|
||||
boolean isStopActionEnabled();
|
||||
void stopServer();
|
||||
public interface ServerNode extends ServersTreeNode {
|
||||
|
||||
boolean isStartActionEnabled(@NotNull Executor executor);
|
||||
void startServer(@NotNull Executor executor);
|
||||
|
||||
boolean isDeployActionEnabled();
|
||||
void deploy(AnActionEvent e);
|
||||
|
||||
boolean isDeployAllActionEnabled();
|
||||
void deployAll();
|
||||
|
||||
void editConfiguration();
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree;
|
||||
|
||||
public interface ServersTreeNode {
|
||||
|
||||
}
|
||||
+77
-75
@@ -3,6 +3,7 @@ package com.intellij.remoteServer.impl.runtime.ui.tree;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.ProgramRunnerUtil;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.execution.impl.RunDialog;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
@@ -18,13 +19,16 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.remoteServer.ServerType;
|
||||
import com.intellij.remoteServer.configuration.RemoteServer;
|
||||
import com.intellij.remoteServer.configuration.RemoteServersManager;
|
||||
import com.intellij.remoteServer.configuration.ServerConfiguration;
|
||||
import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurationManager;
|
||||
import com.intellij.remoteServer.impl.configuration.SingleRemoteServerConfigurable;
|
||||
import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
|
||||
import com.intellij.remoteServer.impl.runtime.deployment.DeploymentTaskImpl;
|
||||
import com.intellij.remoteServer.impl.runtime.log.DeploymentLogManagerImpl;
|
||||
import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
|
||||
@@ -38,6 +42,7 @@ import com.intellij.remoteServer.runtime.deployment.DeploymentStatus;
|
||||
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import icons.RemoteServersIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -160,50 +165,65 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
return ServerConnectionManager.getInstance().getConnection(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
ServerConnection<?> connection = getConnection();
|
||||
return connection != null && connection.getStatus() == ConnectionStatus.CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeployActionEnabled() {
|
||||
return true;
|
||||
public void deploy(AnActionEvent e) {
|
||||
doDeploy(e, DefaultRunExecutor.getRunExecutorInstance(), "Deploy Configuration", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deploy(AnActionEvent e) {
|
||||
final ServerType<? extends ServerConfiguration> serverType = getValue().getType();
|
||||
public void deployWithDebug(AnActionEvent e) {
|
||||
doDeploy(e, DefaultDebugExecutor.getDebugExecutorInstance(), "Deploy and Debug Configuration", false);
|
||||
}
|
||||
|
||||
public void doDeploy(AnActionEvent e, final Executor executor, String popupTitle, boolean canCreate) {
|
||||
final RemoteServer<?> server = getValue();
|
||||
final ServerType<? extends ServerConfiguration> serverType = server.getType();
|
||||
final DeploymentConfigurationManager configurationManager = DeploymentConfigurationManager.getInstance(doGetProject());
|
||||
List<RunnerAndConfigurationSettings> list = new ArrayList<RunnerAndConfigurationSettings>(configurationManager.getDeploymentConfigurations(serverType));
|
||||
list.add(null);
|
||||
ListPopup popup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<RunnerAndConfigurationSettings>("Deploy Configuration", list) {
|
||||
@Override
|
||||
public Icon getIconFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? serverType.getIcon() : null;
|
||||
}
|
||||
List<RunnerAndConfigurationSettings> list
|
||||
= ContainerUtil.filter(configurationManager.getDeploymentConfigurations(serverType),
|
||||
new Condition<RunnerAndConfigurationSettings>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? value.getName() : "Create...";
|
||||
}
|
||||
@Override
|
||||
public boolean value(RunnerAndConfigurationSettings settings) {
|
||||
DeployToServerRunConfiguration configuration =
|
||||
(DeployToServerRunConfiguration)settings.getConfiguration();
|
||||
return StringUtil.equals(server.getName(), configuration.getServerName());
|
||||
}
|
||||
});
|
||||
if (canCreate) {
|
||||
list.add(null);
|
||||
}
|
||||
ListPopup popup =
|
||||
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<RunnerAndConfigurationSettings>(popupTitle, list) {
|
||||
@Override
|
||||
public Icon getIconFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? serverType.getIcon() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(final RunnerAndConfigurationSettings selectedValue, boolean finalChoice) {
|
||||
return doFinalStep(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (selectedValue != null) {
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), selectedValue, DefaultRunExecutor.getRunExecutorInstance());
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? value.getName() : "Create...";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(final RunnerAndConfigurationSettings selectedValue, boolean finalChoice) {
|
||||
return doFinalStep(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (selectedValue != null) {
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), selectedValue, executor);
|
||||
}
|
||||
else {
|
||||
configurationManager.createAndRunConfiguration(serverType, RemoteServerNode.this.getValue());
|
||||
}
|
||||
}
|
||||
else {
|
||||
configurationManager.createAndRunConfiguration(serverType, RemoteServerNode.this.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
if (e.getInputEvent() instanceof MouseEvent) {
|
||||
popup.show(new RelativePoint((MouseEvent)e.getInputEvent()));
|
||||
}
|
||||
@@ -212,45 +232,10 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStopActionEnabled() {
|
||||
return isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopServer() {
|
||||
ServerConnection<?> connection = getConnection();
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editConfiguration() {
|
||||
ShowSettingsUtil.getInstance().editConfigurable(doGetProject(), new SingleRemoteServerConfigurable(getValue(), null, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStartActionEnabled(@NotNull Executor executor) {
|
||||
ServerConnection connection = getConnection();
|
||||
return executor.equals(DefaultRunExecutor.getRunExecutorInstance()) &&
|
||||
(connection == null || connection.getStatus() == ConnectionStatus.DISCONNECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startServer(@NotNull Executor executor) {
|
||||
ServerConnectionManager.getInstance().getOrCreateConnection(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeployAllActionEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deployAll() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Icon getStatusIcon(final ConnectionStatus status) {
|
||||
switch (status) {
|
||||
@@ -278,23 +263,42 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRedeployActionEnabled() {
|
||||
public boolean isDeployActionVisible() {
|
||||
DeploymentTask<?> deploymentTask = getValue().getDeploymentTask();
|
||||
return deploymentTask instanceof DeploymentTaskImpl<?> && ((DeploymentTaskImpl)deploymentTask).getExecutionEnvironment().getRunnerAndConfigurationSettings() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redeploy() {
|
||||
public boolean isDeployActionEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deploy() {
|
||||
doDeploy(DefaultRunExecutor.getRunExecutorInstance());
|
||||
}
|
||||
|
||||
public void doDeploy(Executor executor) {
|
||||
DeploymentTask<?> deploymentTask = getValue().getDeploymentTask();
|
||||
if (deploymentTask != null) {
|
||||
ExecutionEnvironment environment = ((DeploymentTaskImpl)deploymentTask).getExecutionEnvironment();
|
||||
RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings();
|
||||
if (settings != null) {
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), settings, DefaultRunExecutor.getRunExecutorInstance());
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), settings, executor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugActionVisible() {
|
||||
return myParentNode.getValue().getType().createDebugConnector() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deployWithDebug() {
|
||||
doDeploy(DefaultDebugExecutor.getDebugExecutorInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUndeployActionEnabled() {
|
||||
DeploymentRuntime runtime = getValue().getRuntime();
|
||||
@@ -309,12 +313,10 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEditConfigurationActionEnabled() {
|
||||
public boolean isEditConfigurationActionVisible() {
|
||||
return getValue().getDeploymentTask() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editConfiguration() {
|
||||
DeploymentTask<?> task = getValue().getDeploymentTask();
|
||||
if (task != null) {
|
||||
@@ -396,7 +398,7 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeploymentLogNode extends AbstractTreeNode<Pair<LoggingHandlerImpl, String>> implements LogProvidingNode {
|
||||
public class DeploymentLogNode extends AbstractTreeNode<Pair<LoggingHandlerImpl, String>> implements ServersTreeNode, LogProvidingNode {
|
||||
@NotNull private final DeploymentNodeImpl myDeploymentNode;
|
||||
|
||||
public DeploymentLogNode(@NotNull Pair<LoggingHandlerImpl, String> value, @NotNull DeploymentNodeImpl deploymentNode) {
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChooseDeploymentAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public ChooseDeploymentAction() {
|
||||
super("Deploy", "Deploy a chosen item to the selected remote server", AllIcons.Nodes.Deploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, ServersTreeStructure.RemoteServerNode node) {
|
||||
node.deploy(e);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChooseDeploymentWithDebugAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public ChooseDeploymentWithDebugAction() {
|
||||
super("Debug", "Deploy and debug a chosen item on the selected remote server", AllIcons.Actions.StartDebugger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, ServersTreeStructure.RemoteServerNode node) {
|
||||
node.deployWithDebug(e);
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class DebugServerAction extends RunServerActionBase {
|
||||
public DebugServerAction() {
|
||||
super("Debug", "Start the selected server in debug mode", AllIcons.Actions.StartDebugger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Executor getExecutor() {
|
||||
return DefaultDebugExecutor.getDebugExecutorInstance();
|
||||
}
|
||||
}
|
||||
+23
-40
@@ -1,67 +1,50 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class DeployAction extends ServersTreeActionBase {
|
||||
public class DeployAction extends ServersTreeAction<DeploymentNode> {
|
||||
|
||||
public DeployAction() {
|
||||
super("Deploy", "Deploy the selected item", AllIcons.Nodes.Deploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable ServersToolWindowContent content) {
|
||||
if (content != null) {
|
||||
Set<DeploymentNode> nodes = content.getSelectedDeploymentNodes();
|
||||
if (nodes.size() == 1) {
|
||||
DeploymentNode node = nodes.iterator().next();
|
||||
if (node.isDeployed()) {
|
||||
presentation.setText("Redeploy");
|
||||
presentation.setDescription("Redeploy '" + node.getDeploymentName() + "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
presentation.setText(getTemplatePresentation().getText());
|
||||
presentation.setDescription(getTemplatePresentation().getDescription());
|
||||
protected Class<DeploymentNode> getTargetNodeClass() {
|
||||
return DeploymentNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<DeploymentNode> deploymentNodes = content.getSelectedDeploymentNodes();
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
if (deploymentNodes.size() + serverNodes.size() != 1) return false;
|
||||
for (DeploymentNode node : deploymentNodes) {
|
||||
if (!node.isRedeployActionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable DeploymentNode node) {
|
||||
if (node != null && node.isDeployed()) {
|
||||
presentation.setText("Redeploy");
|
||||
presentation.setDescription("Redeploy '" + node.getDeploymentName() + "'");
|
||||
}
|
||||
for (ServerNode serverNode : serverNodes) {
|
||||
if (!serverNode.isDeployActionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
presentation.setText(getTemplatePresentation().getText());
|
||||
presentation.setDescription(getTemplatePresentation().getDescription());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
for (DeploymentNode node : content.getSelectedDeploymentNodes()) {
|
||||
node.redeploy();
|
||||
}
|
||||
for (ServerNode node : content.getSelectedServerNodes()) {
|
||||
node.deploy(e);
|
||||
}
|
||||
protected boolean isVisible4(DeploymentNode node) {
|
||||
return node.isDeployActionVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(DeploymentNode node) {
|
||||
return node.isDeployActionEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(DeploymentNode node) {
|
||||
node.deploy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class DeployAllAction extends ServerActionBase {
|
||||
|
||||
public DeployAllAction() {
|
||||
super("Deploy All", "Deploy all the artifacts of the selected server", AllIcons.Nodes.Deploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performAction(@NotNull ServerNode serverNode) {
|
||||
if (serverNode.isDeployAllActionEnabled()) {
|
||||
serverNode.deployAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForServer(@NotNull ServerNode serverNode) {
|
||||
return serverNode.isDeployAllActionEnabled();
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
|
||||
public class DeployWithDebugAction extends ServersTreeAction<DeploymentNode> {
|
||||
|
||||
public DeployWithDebugAction() {
|
||||
super("Debug", "Deploy and debug the selected item", AllIcons.Actions.StartDebugger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<DeploymentNode> getTargetNodeClass() {
|
||||
return DeploymentNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisible4(DeploymentNode node) {
|
||||
return node.isDeployActionVisible() && node.isDebugActionVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(DeploymentNode node) {
|
||||
return node.isDeployActionEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(DeploymentNode node) {
|
||||
node.deployWithDebug();
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class DeploymentActionBase extends ServersTreeActionBase {
|
||||
protected DeploymentActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
protected abstract void perform(@NotNull List<DeploymentNode> nodes, ServersToolWindowContent content, AnActionEvent e);
|
||||
|
||||
protected abstract boolean isApplicable(@NotNull DeploymentNode node);
|
||||
|
||||
@Override
|
||||
public void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
List<DeploymentNode> toPerform = new ArrayList<DeploymentNode>();
|
||||
for (DeploymentNode node : content.getSelectedDeploymentNodes()) {
|
||||
if (isApplicable(node)) {
|
||||
toPerform.add(node);
|
||||
}
|
||||
}
|
||||
if (!toPerform.isEmpty()) {
|
||||
perform(toPerform, content, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<?> selectedElements = content.getBuilder().getSelectedElements();
|
||||
if (selectedElements.isEmpty() || selectedElements.size() != content.getSelectedDeploymentNodes().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (DeploymentNode node : content.getSelectedDeploymentNodes()) {
|
||||
if (!isApplicable(node)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
|
||||
public class DeploymentConfigAction extends EditConfigurationActionBase<ServersTreeStructure.DeploymentNodeImpl> {
|
||||
|
||||
public DeploymentConfigAction() {
|
||||
super("Edit the selected deployment run configuration");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.DeploymentNodeImpl> getTargetNodeClass() {
|
||||
return ServersTreeStructure.DeploymentNodeImpl.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisible4(ServersTreeStructure.DeploymentNodeImpl node) {
|
||||
return node.isEditConfigurationActionVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.DeploymentNodeImpl node) {
|
||||
node.editConfiguration();
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class EditConfigurationAction extends ServersTreeActionBase {
|
||||
public EditConfigurationAction() {
|
||||
super("Edit Configuration", "Edit configuration of the selected server", AllIcons.Actions.EditSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<DeploymentNode> deploymentNodes = content.getSelectedDeploymentNodes();
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
if (deploymentNodes.size() == 1) {
|
||||
deploymentNodes.iterator().next().editConfiguration();
|
||||
}
|
||||
else {
|
||||
serverNodes.iterator().next().editConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<DeploymentNode> deploymentNodes = content.getSelectedDeploymentNodes();
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
if (deploymentNodes.size() + serverNodes.size() != 1) return false;
|
||||
if (deploymentNodes.size() == 1) {
|
||||
return deploymentNodes.iterator().next().isEditConfigurationActionEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeNode;
|
||||
|
||||
public abstract class EditConfigurationActionBase<T extends ServersTreeNode> extends ServersTreeAction<T> {
|
||||
|
||||
public EditConfigurationActionBase(String description) {
|
||||
super("Edit Configuration", description, AllIcons.Actions.EditSource);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
|
||||
public class RemoteServerConfigAction extends EditConfigurationActionBase<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public RemoteServerConfigAction() {
|
||||
super("Edit the selected remote server configuration");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) {
|
||||
node.editConfiguration();
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.remoteServer.runtime.ServerConnectionManager;
|
||||
|
||||
public class RemoteServerConnectAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public RemoteServerConnectAction() {
|
||||
super("Connect", "Connect to the selected remote server", AllIcons.Actions.Execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(ServersTreeStructure.RemoteServerNode node) {
|
||||
return !node.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) {
|
||||
ServerConnectionManager.getInstance().getOrCreateConnection(node.getValue());
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.remoteServer.runtime.ServerConnection;
|
||||
import com.intellij.remoteServer.runtime.ServerConnectionManager;
|
||||
|
||||
public class RemoteServerDisconnectAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public RemoteServerDisconnectAction() {
|
||||
super("Disconnect", "Disconnect from the selected remote server", AllIcons.Actions.Suspend);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(ServersTreeStructure.RemoteServerNode node) {
|
||||
return node.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) {
|
||||
ServerConnection<?> connection = ServerConnectionManager.getInstance().getConnection(node.getValue());
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class RunServerAction extends RunServerActionBase {
|
||||
|
||||
public RunServerAction() {
|
||||
super("Run/Connect", "Run/Connect to the selected server", AllIcons.Actions.Execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Executor getExecutor() {
|
||||
return DefaultRunExecutor.getRunExecutorInstance();
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class RunServerActionBase extends ServerActionBase {
|
||||
|
||||
protected RunServerActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
protected void performAction(@NotNull ServerNode serverNode) {
|
||||
if (serverNode.isStartActionEnabled(getExecutor())) {
|
||||
serverNode.startServer(getExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForServer(@NotNull ServerNode serverNode) {
|
||||
return serverNode.isStartActionEnabled(getExecutor());
|
||||
}
|
||||
|
||||
protected abstract Executor getExecutor();
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class ServerActionBase extends ServersTreeActionBase {
|
||||
|
||||
protected ServerActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<ServerNode> selectedServerNodes = content.getSelectedServerNodes();
|
||||
Set<?> selectedElements = content.getBuilder().getSelectedElements();
|
||||
if (selectedElements.size() != selectedServerNodes.size() || selectedElements.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ServerNode selectedServer : selectedServerNodes) {
|
||||
if (!isEnabledForServer(selectedServer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
for (ServerNode node : content.getSelectedServerNodes()) {
|
||||
performAction(node);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void performAction(@NotNull ServerNode serverNode);
|
||||
|
||||
protected abstract boolean isEnabledForServer(@NotNull ServerNode serverNode);
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class ServersTreeAction<T extends ServersTreeNode> extends AnAction {
|
||||
|
||||
protected ServersTreeAction(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
Presentation presentation = e.getPresentation();
|
||||
T targetNode = getTargetNode(e);
|
||||
|
||||
boolean visible = false;
|
||||
boolean enabled = false;
|
||||
|
||||
if (targetNode != null) {
|
||||
visible = isVisible4(targetNode);
|
||||
if (visible) {
|
||||
enabled = isEnabled4(targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
presentation.setVisible(visible);
|
||||
presentation.setEnabled(enabled);
|
||||
updatePresentation(presentation, targetNode);
|
||||
}
|
||||
|
||||
private T getTargetNode(AnActionEvent e) {
|
||||
ServersToolWindowContent content = getContent(e);
|
||||
if (content == null) {
|
||||
return null;
|
||||
}
|
||||
Set<Object> selectedElements = content.getBuilder().getSelectedElements();
|
||||
if (selectedElements.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
ServersTreeNode node = (ServersTreeNode)selectedElements.iterator().next();
|
||||
Class<T> targetNodeClass = getTargetNodeClass();
|
||||
if (!targetNodeClass.isInstance(node)) {
|
||||
return null;
|
||||
}
|
||||
return targetNodeClass.cast(node);
|
||||
}
|
||||
|
||||
private static ServersToolWindowContent getContent(AnActionEvent e) {
|
||||
return e.getData(ServersToolWindowContent.KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
T targetNode = getTargetNode(e);
|
||||
if (targetNode != null && isVisible4(targetNode) && isEnabled4(targetNode)) {
|
||||
doActionPerformed(getContent(e), e, targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean isVisible4(T node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isEnabled4(T node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable T node) {
|
||||
}
|
||||
|
||||
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, T node) {
|
||||
doActionPerformed(node);
|
||||
}
|
||||
|
||||
protected void doActionPerformed(T node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract Class<T> getTargetNodeClass();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class ServersTreeActionBase extends AnAction {
|
||||
|
||||
protected ServersTreeActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
ServersToolWindowContent content = e.getData(ServersToolWindowContent.KEY);
|
||||
Presentation presentation = e.getPresentation();
|
||||
presentation.setEnabled(content != null && isEnabled(content, e));
|
||||
updatePresentation(presentation, content);
|
||||
}
|
||||
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable ServersToolWindowContent content) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
ServersToolWindowContent content = e.getData(ServersToolWindowContent.KEY);
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
doActionPerformed(content, e);
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e);
|
||||
|
||||
protected abstract void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e);
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class SingleServerActionBase extends ServersTreeActionBase {
|
||||
protected SingleServerActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
doActionPerformed(content, content.getSelectedServerNodes().iterator().next());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
return content.getBuilder().getSelectedElements().size() == serverNodes.size() && serverNodes.size() == 1 &&
|
||||
isEnabledForServer(serverNodes.iterator().next());
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabledForServer(ServerNode serverNode);
|
||||
|
||||
protected abstract void doActionPerformed(@NotNull ServersToolWindowContent content, @NotNull ServerNode server);
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class StopServerAction extends ServerActionBase {
|
||||
|
||||
public StopServerAction() {
|
||||
super("Stop/Disconnect", "Stop/disconnect from the selected server", AllIcons.Actions.Suspend);
|
||||
}
|
||||
|
||||
protected void performAction(@NotNull ServerNode serverNode) {
|
||||
if (serverNode.isStopActionEnabled()) {
|
||||
serverNode.stopServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForServer(@NotNull ServerNode serverNode) {
|
||||
return serverNode.isStopActionEnabled();
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -1,30 +1,29 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class UndeployAction extends DeploymentActionBase {
|
||||
public class UndeployAction extends ServersTreeAction<DeploymentNode> {
|
||||
|
||||
public UndeployAction() {
|
||||
super("Undeploy", "Undeploy the selected item", AllIcons.Nodes.Undeploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isApplicable(@NotNull DeploymentNode node) {
|
||||
protected Class<DeploymentNode> getTargetNodeClass() {
|
||||
return DeploymentNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(DeploymentNode node) {
|
||||
return node.isUndeployActionEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(@NotNull List<DeploymentNode> nodes, ServersToolWindowContent content, AnActionEvent e) {
|
||||
for (DeploymentNode node : nodes) {
|
||||
node.undeploy();
|
||||
}
|
||||
protected void doActionPerformed(DeploymentNode node) {
|
||||
node.undeploy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class DateFormatUtilTest {
|
||||
|
||||
@Test
|
||||
public void testBasics() throws ParseException {
|
||||
Clock.setTime(2004, 11, 10, 17, 10);
|
||||
Clock.setTime(2004, Calendar.DECEMBER, 10, 17, 10);
|
||||
|
||||
doTestPrettyDate("Today", "10.12.2004 17.00.00");
|
||||
doTestPrettyDate("Today", "10.12.2004 00.00.00");
|
||||
@@ -49,7 +49,7 @@ public class DateFormatUtilTest {
|
||||
|
||||
@Test
|
||||
public void testTime() throws Exception {
|
||||
Clock.setTime(2004, 11, 10, 17, 10, 15);
|
||||
Clock.setTime(1980, Calendar.DECEMBER, 10, 17, 10, 15);
|
||||
|
||||
if (SystemInfo.isMac) {
|
||||
assertEquals("17:10", DateFormatUtil.formatTime(Clock.getTime()));
|
||||
@@ -60,7 +60,7 @@ public class DateFormatUtilTest {
|
||||
assertEquals("17:10:15", printTimeForLocale("de_DE.UTF-8", Clock.getTime()));
|
||||
}
|
||||
else if (SystemInfo.isWinVistaOrNewer) {
|
||||
long time = new Date().getTime();
|
||||
long time = Clock.getTime();
|
||||
assertEquals(printWindowsTime(time), DateFormatUtil.formatTimeWithSeconds(time));
|
||||
}
|
||||
else {
|
||||
@@ -73,7 +73,7 @@ public class DateFormatUtilTest {
|
||||
|
||||
@Test
|
||||
public void testPrettyDateTime() throws ParseException {
|
||||
Clock.setTime(2004, 11, 10, 17, 0);
|
||||
Clock.setTime(2004, Calendar.DECEMBER, 10, 17, 0);
|
||||
doTestDateTime("Moments ago", "10.12.2004 16.59.31");
|
||||
doTestDateTime("A minute ago", "10.12.2004 16.59.29");
|
||||
doTestDateTime("5 minutes ago", "10.12.2004 16.55.00");
|
||||
@@ -82,7 +82,7 @@ public class DateFormatUtilTest {
|
||||
doTestDateTime("Yesterday " + DateFormatUtil.formatTime(DATE_FORMAT.parse("09.12.2004 15.00.00")), "09.12.2004 15.00.00");
|
||||
doTestDateTime("Today " + DateFormatUtil.formatTime(DATE_FORMAT.parse("10.12.2004 19.00.00")), "10.12.2004 19.00.00");
|
||||
|
||||
Clock.setTime(2004, 0, 1, 15, 53);
|
||||
Clock.setTime(2004, Calendar.JANUARY, 1, 15, 53);
|
||||
doTestDateTime(DateFormatUtil.formatDateTime(DATE_FORMAT.parse("01.01.2003 15.53.00")), "01.01.2003 15.53.00");
|
||||
doTestDateTime("Yesterday " + DateFormatUtil.formatTime(DATE_FORMAT.parse("31.12.2003 15.00.00")), "31.12.2003 15.00.00");
|
||||
}
|
||||
|
||||
+32
-23
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.RefactoringChangeUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
@@ -243,12 +244,9 @@ public class UnnecessaryUnboxingInspection extends BaseInspection {
|
||||
if (!(expression instanceof PsiMethodCallExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethodCallExpression methodCallExpression =
|
||||
(PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression =
|
||||
methodCallExpression.getMethodExpression();
|
||||
final PsiExpression qualifier =
|
||||
methodExpression.getQualifierExpression();
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -261,31 +259,45 @@ public class UnnecessaryUnboxingInspection extends BaseInspection {
|
||||
return false;
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
final String unboxingMethod =
|
||||
s_unboxingMethods.get(qualifierTypeName);
|
||||
final String unboxingMethod = s_unboxingMethods.get(qualifierTypeName);
|
||||
return unboxingMethod.equals(methodName);
|
||||
}
|
||||
|
||||
private boolean isSameMethodCalledWithoutUnboxing(
|
||||
@NotNull PsiCallExpression callExpression,
|
||||
@NotNull PsiMethodCallExpression unboxingExpression) {
|
||||
final PsiExpressionList argumentList =
|
||||
callExpression.getArgumentList();
|
||||
private boolean isSameMethodCalledWithoutUnboxing(@NotNull PsiCallExpression callExpression,
|
||||
@NotNull PsiMethodCallExpression unboxingExpression) {
|
||||
final PsiExpressionList argumentList = callExpression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
final PsiMethod originalMethod =
|
||||
callExpression.resolveMethod();
|
||||
final PsiMethod originalMethod = callExpression.resolveMethod();
|
||||
if (originalMethod == null) {
|
||||
return false;
|
||||
}
|
||||
final String name = originalMethod.getName();
|
||||
final PsiClass containingClass =
|
||||
originalMethod.getContainingClass();
|
||||
|
||||
final PsiExpression qualifierExpression;
|
||||
if (callExpression instanceof PsiMethodCallExpression) {
|
||||
qualifierExpression = ((PsiMethodCallExpression)callExpression).getMethodExpression().getQualifierExpression();
|
||||
} else if (callExpression instanceof PsiNewExpression) {
|
||||
qualifierExpression = ((PsiNewExpression)callExpression).getQualifier();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiClass containingClass;
|
||||
if (qualifierExpression == null) {
|
||||
final PsiElement scope = callExpression.resolveMethodGenerics().getCurrentFileResolveScope();
|
||||
containingClass = scope instanceof PsiClass ? (PsiClass)scope : null;
|
||||
}
|
||||
else {
|
||||
containingClass = PsiUtil.resolveClassInType(GenericsUtil.getVariableTypeByExpressionType(qualifierExpression.getType()));
|
||||
}
|
||||
|
||||
if (containingClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType[] types = PsiType.createArray(expressions.length);
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
final PsiExpression expression = expressions[i];
|
||||
@@ -294,20 +306,17 @@ public class UnnecessaryUnboxingInspection extends BaseInspection {
|
||||
if (!(type instanceof PsiPrimitiveType)) {
|
||||
return false;
|
||||
}
|
||||
final PsiPrimitiveType primitiveType =
|
||||
(PsiPrimitiveType)type;
|
||||
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)type;
|
||||
types[i] = primitiveType.getBoxedType(unboxingExpression);
|
||||
}
|
||||
else {
|
||||
types[i] = type;
|
||||
}
|
||||
}
|
||||
final PsiMethod[] methods =
|
||||
containingClass.findMethodsByName(name, true);
|
||||
final PsiMethod[] methods = containingClass.findMethodsByName(name, true);
|
||||
for (final PsiMethod method : methods) {
|
||||
if (!originalMethod.equals(method)) {
|
||||
if (MethodCallUtils.isApplicable(method,
|
||||
PsiSubstitutor.EMPTY, types)) {
|
||||
if (MethodCallUtils.isApplicable(method, PsiSubstitutor.EMPTY, types)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -38,4 +38,19 @@ public class UnnecessaryUnboxing {
|
||||
Integer boxcutter(Integer i) {
|
||||
return i.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class B23 {
|
||||
public void set(double value) {}
|
||||
}
|
||||
class A23 extends B23 {
|
||||
public void set(Object value) {}
|
||||
private A23() {
|
||||
Object o = 2d;
|
||||
set(((Double) o).doubleValue());
|
||||
|
||||
B23 b23 = new B23();
|
||||
b23.set(((Double) o).doubleValue());
|
||||
}
|
||||
}
|
||||
+13
@@ -43,4 +43,17 @@ public class UnnecessaryUnboxing {
|
||||
byte cast(Integer v) {
|
||||
return (byte)v.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class B23 {
|
||||
public void set(double value) {}
|
||||
}
|
||||
class A23 extends B23 {
|
||||
public void set(Object value) {}
|
||||
private A23() {
|
||||
Object o = 2d;
|
||||
B23 b23 = new B23();
|
||||
b23.set(((Double) o).doubleValue());
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -55,5 +55,10 @@
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unnecessary unboxing</problem_class>
|
||||
<description>Unnecessary unboxing <code>b.byteValue()</code> #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>UnnecessaryUnboxing.java</file>
|
||||
<line>57</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unnecessary unboxing</problem_class>
|
||||
<description>Unnecessary unboxing <code>((Double) o).doubleValue()</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -26,7 +26,6 @@ import com.intellij.tasks.TaskBundle;
|
||||
import com.intellij.tasks.TaskRepositoryType;
|
||||
import com.intellij.tasks.impl.BaseRepository;
|
||||
import com.intellij.tasks.impl.BaseRepositoryImpl;
|
||||
import com.intellij.tasks.impl.TaskUtil;
|
||||
import com.intellij.tasks.impl.httpclient.ResponseUtil;
|
||||
import com.intellij.tasks.trello.model.TrelloBoard;
|
||||
import com.intellij.tasks.trello.model.TrelloCard;
|
||||
@@ -320,8 +319,6 @@ public final class TrelloRepository extends BaseRepositoryImpl {
|
||||
HttpClient client = getHttpClient();
|
||||
client.executeMethod(method);
|
||||
String entityContent = ResponseUtil.getResponseContentAsString(method);
|
||||
TaskUtil.prettyFormatJsonToLog(LOG, entityContent);
|
||||
// LOG.debug("Response size: " + method.getResponseHeader("Content-Length").getValue() + " bytes");
|
||||
if (method.getStatusCode() != HttpStatus.SC_OK) {
|
||||
Header header = method.getResponseHeader("Content-Type");
|
||||
if (header != null && header.getValue().startsWith("text/plain")) {
|
||||
|
||||
@@ -43,7 +43,7 @@ import java.util.List;
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepository> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.trello.TrelloRepositoryEditor");
|
||||
private static final Logger LOG = Logger.getInstance(TrelloRepositoryEditor.class);
|
||||
|
||||
private static final TrelloBoard UNSPECIFIED_BOARD = new TrelloBoard() {
|
||||
@NotNull
|
||||
@@ -83,9 +83,10 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
String password = String.valueOf(myPasswordText.getPassword());
|
||||
if (password.equals(myRepository.getPassword())) {
|
||||
if (password.isEmpty() || password.equals(myRepository.getPassword())) {
|
||||
return;
|
||||
}
|
||||
LOG.debug("Authentication token was changed");
|
||||
myRepository.setPassword(password);
|
||||
new BoardsDownloader(UNSPECIFIED_BOARD) {
|
||||
@Override
|
||||
@@ -119,7 +120,6 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
}
|
||||
});
|
||||
myBoardComboBox.setRenderer(new TrelloBoardRenderer("Set token first"));
|
||||
myListComboBox.setRenderer(new TrelloListRenderer("Select board first"));
|
||||
|
||||
myListComboBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
@@ -132,12 +132,14 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
}
|
||||
}
|
||||
});
|
||||
myListComboBox.setRenderer(new TrelloListRenderer("Select board first"));
|
||||
|
||||
// Initial setup:
|
||||
if (myRepository.getCurrentUser() != null) {
|
||||
new BoardsDownloader(myRepository.getCurrentBoard()) {
|
||||
@Override
|
||||
protected List<TrelloBoard> download() throws Exception {
|
||||
LOG.debug("Updating information about boards available to user when repository setting are shown");
|
||||
List<TrelloBoard> boards = super.download();
|
||||
if (myBoard == null) {
|
||||
return boards;
|
||||
@@ -157,6 +159,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
new ListsDownloader(myRepository.getCurrentList()) {
|
||||
@Override
|
||||
protected List<TrelloList> download() throws Exception {
|
||||
LOG.debug("Updating information about lists of board " + myRepository.getCurrentBoard() + " when repository setting are shown");
|
||||
List<TrelloList> lists = super.download();
|
||||
if (myList == null) {
|
||||
return lists;
|
||||
@@ -266,6 +269,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
return myRepository.fetchUserBoards();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void updateUI(List<TrelloBoard> boards) {
|
||||
myBoardComboBox.setModel(new DefaultComboBoxModel(boards.toArray()));
|
||||
@@ -296,6 +300,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
return myRepository.fetchBoardLists();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void updateUI(List<TrelloList> lists) {
|
||||
myListComboBox.setModel(new DefaultComboBoxModel(lists.toArray()));
|
||||
|
||||
+4
-1
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.plugins.coursecreator.actions;
|
||||
|
||||
import com.intellij.ide.IdeView;
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.ide.util.DirectoryChooserUtil;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
@@ -20,7 +21,7 @@ import javax.swing.*;
|
||||
|
||||
public class CCChangeCourseInfo extends DumbAwareAction {
|
||||
public CCChangeCourseInfo() {
|
||||
super("Change course information", "Change course information", null);
|
||||
super("Change Course information", "Change Course Information", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,6 +86,7 @@ public class CCChangeCourseInfo extends DumbAwareAction {
|
||||
course.setAuthor(panel.getAuthor());
|
||||
course.setName(panel.getName());
|
||||
course.setDescription(panel.getDescription());
|
||||
ProjectView.getInstance(project).refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +95,7 @@ public class CCChangeCourseInfo extends DumbAwareAction {
|
||||
CCNewProjectPanel myNewProjectPanel;
|
||||
public ChangeCourseInfoDialog(@Nullable Project project, CCNewProjectPanel panel) {
|
||||
super(project);
|
||||
setTitle("Change Course Information");
|
||||
myNewProjectPanel = panel;
|
||||
init();
|
||||
}
|
||||
|
||||
+1
@@ -84,6 +84,7 @@ public class CCRunTestsAction extends AnAction {
|
||||
if (lessonDir == null) return;
|
||||
if (course == null) return;
|
||||
final Lesson lesson = course.getLesson(lessonDir.getName());
|
||||
if (lesson == null) return;
|
||||
final Task task = lesson.getTask(taskDir.getName());
|
||||
if (task == null) {
|
||||
presentation.setVisible(false);
|
||||
|
||||
@@ -54,23 +54,28 @@ public class PyExecuteFileLineMarkerProvider implements LineMarkerProvider {
|
||||
return new LineMarkerGutterIconRenderer<PsiElement>(this){
|
||||
@Override
|
||||
public AnAction getClickAction() {
|
||||
final DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new PyRunCurrentFileAction());
|
||||
final PyExecuteFileExtensionPoint[] extensions =
|
||||
ApplicationManager.getApplication().getExtensions(PyExecuteFileExtensionPoint.EP_NAME);
|
||||
for (PyExecuteFileExtensionPoint extension : extensions) {
|
||||
final AnAction action = extension.getRunAction();
|
||||
group.add(action);
|
||||
}
|
||||
if (group.getChildrenCount() == 1) {
|
||||
return new PyRunCurrentFileAction();
|
||||
}
|
||||
|
||||
return new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
final ListPopup popup =
|
||||
new PopupFactoryImpl().createActionGroupPopup(null, group, e.getDataContext(), false, false, false, null, 5);
|
||||
popup.showInBestPositionFor(e.getDataContext());
|
||||
final DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new PyRunCurrentFileAction());
|
||||
final PyExecuteFileExtensionPoint[] extensions =
|
||||
ApplicationManager.getApplication().getExtensions(PyExecuteFileExtensionPoint.EP_NAME);
|
||||
for (PyExecuteFileExtensionPoint extension : extensions) {
|
||||
final AnAction action = extension.getRunAction();
|
||||
action.update(e);
|
||||
if (e.getPresentation().isEnabled())
|
||||
group.add(action);
|
||||
}
|
||||
if (group.getChildrenCount() == 1) {
|
||||
new PyRunCurrentFileAction().actionPerformed(e);
|
||||
}
|
||||
else {
|
||||
final ListPopup popup =
|
||||
new PopupFactoryImpl().createActionGroupPopup(null, group, e.getDataContext(), false, false, false, null, 5);
|
||||
popup.showInBestPositionFor(e.getDataContext());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
package com.intellij.psi.impl.source.xml;
|
||||
|
||||
import com.intellij.ide.highlighter.DTDFileType;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
@@ -49,8 +52,6 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef {
|
||||
super(XmlElementType.XML_ENTITY_REF);
|
||||
}
|
||||
|
||||
private static final Key<String> EVALUATION_IN_PROCESS = Key.create("EvalKey");
|
||||
|
||||
@Override
|
||||
public XmlEntityDecl resolve(PsiFile targetFile) {
|
||||
String text = getText();
|
||||
@@ -77,12 +78,12 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef {
|
||||
if (value == null) {
|
||||
final PsiManager manager = element.getManager();
|
||||
if(manager == null){
|
||||
return resolveEntity(targetElement, entityName, containingFile).getValue();
|
||||
return doResolveEntity(targetElement, entityName, containingFile).getValue();
|
||||
}
|
||||
value = CachedValuesManager.getManager(manager.getProject()).createCachedValue(new CachedValueProvider<XmlEntityDecl>() {
|
||||
@Override
|
||||
public Result<XmlEntityDecl> compute() {
|
||||
return resolveEntity(targetElement, entityName, containingFile);
|
||||
return doResolveEntity(targetElement, entityName, containingFile);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -95,95 +96,94 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef {
|
||||
|
||||
private static final Key<Boolean> DISABLE_ENTITY_EXPAND = Key.create("disable.entity.expand");
|
||||
|
||||
private static CachedValueProvider.Result<XmlEntityDecl> resolveEntity(final PsiElement targetElement, final String entityName, PsiFile contextFile) {
|
||||
if (targetElement.getUserData(EVALUATION_IN_PROCESS) != null) {
|
||||
return new CachedValueProvider.Result<XmlEntityDecl>(null,targetElement);
|
||||
}
|
||||
try {
|
||||
targetElement.putUserData(EVALUATION_IN_PROCESS, "");
|
||||
final List<PsiElement> deps = new ArrayList<PsiElement>();
|
||||
final XmlEntityDecl[] result = {null};
|
||||
private static CachedValueProvider.Result<XmlEntityDecl> doResolveEntity(final PsiElement targetElement,
|
||||
final String entityName,
|
||||
final PsiFile contextFile) {
|
||||
return RecursionManager.doPreventingRecursion(targetElement, true, new Computable<CachedValueProvider.Result<XmlEntityDecl>>() {
|
||||
@Override
|
||||
public CachedValueProvider.Result<XmlEntityDecl> compute() {
|
||||
final List<PsiElement> deps = new ArrayList<PsiElement>();
|
||||
final XmlEntityDecl[] result = {null};
|
||||
|
||||
PsiElementProcessor processor = new PsiElementProcessor() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiElement element) {
|
||||
if (element instanceof XmlDoctype) {
|
||||
XmlDoctype xmlDoctype = (XmlDoctype)element;
|
||||
final String dtdUri = getDtdForEntity(xmlDoctype);
|
||||
if (dtdUri != null) {
|
||||
XmlFile file = XmlUtil.getContainingFile(element);
|
||||
if (file == null) return true;
|
||||
final XmlFile xmlFile = XmlUtil.findNamespace(file, dtdUri);
|
||||
if (xmlFile != null) {
|
||||
if (xmlFile != targetElement) {
|
||||
deps.add(xmlFile);
|
||||
if(!XmlUtil.processXmlElements(xmlFile, this,true)) return false;
|
||||
PsiElementProcessor processor = new PsiElementProcessor() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiElement element) {
|
||||
if (element instanceof XmlDoctype) {
|
||||
XmlDoctype xmlDoctype = (XmlDoctype)element;
|
||||
final String dtdUri = getDtdForEntity(xmlDoctype);
|
||||
if (dtdUri != null) {
|
||||
XmlFile file = XmlUtil.getContainingFile(element);
|
||||
if (file == null) return true;
|
||||
final XmlFile xmlFile = XmlUtil.findNamespace(file, dtdUri);
|
||||
if (xmlFile != null) {
|
||||
if (xmlFile != targetElement) {
|
||||
deps.add(xmlFile);
|
||||
if (!XmlUtil.processXmlElements(xmlFile, this, true)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
final XmlMarkupDecl markupDecl = xmlDoctype.getMarkupDecl();
|
||||
if (markupDecl != null) {
|
||||
if (!XmlUtil.processXmlElements(markupDecl, this, true)) return false;
|
||||
}
|
||||
}
|
||||
final XmlMarkupDecl markupDecl = xmlDoctype.getMarkupDecl();
|
||||
if (markupDecl != null) {
|
||||
if (!XmlUtil.processXmlElements(markupDecl, this, true)) return false;
|
||||
else if (element instanceof XmlEntityDecl) {
|
||||
XmlEntityDecl entityDecl = (XmlEntityDecl)element;
|
||||
final String declName = entityDecl.getName();
|
||||
if (StringUtil.equals(declName, entityName)) {
|
||||
result[0] = entityDecl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (element instanceof XmlEntityDecl) {
|
||||
XmlEntityDecl entityDecl = (XmlEntityDecl)element;
|
||||
final String declName = entityDecl.getName();
|
||||
if (declName.equals(entityName)) {
|
||||
result[0] = entityDecl;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
FileViewProvider provider = targetElement.getContainingFile().getViewProvider();
|
||||
deps.add(provider.getPsi(provider.getBaseLanguage()));
|
||||
|
||||
boolean notfound = PsiTreeUtil.processElements(targetElement, processor);
|
||||
if (notfound) {
|
||||
if (contextFile != targetElement && contextFile != null && contextFile.isValid()) {
|
||||
notfound = PsiTreeUtil.processElements(contextFile, processor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
FileViewProvider provider = targetElement.getContainingFile().getViewProvider();
|
||||
deps.add(provider.getPsi(provider.getBaseLanguage()));
|
||||
|
||||
boolean notfound = PsiTreeUtil.processElements(targetElement, processor);
|
||||
if (notfound) {
|
||||
if (contextFile != targetElement && contextFile != null && contextFile.isValid()) {
|
||||
notfound = PsiTreeUtil.processElements(contextFile, processor);
|
||||
}
|
||||
}
|
||||
if (notfound && // no dtd ref at all
|
||||
targetElement instanceof XmlFile &&
|
||||
deps.size() == 1 &&
|
||||
((XmlFile)targetElement).getFileType() != DTDFileType.INSTANCE
|
||||
) {
|
||||
XmlDocument document = ((XmlFile)targetElement).getDocument();
|
||||
final XmlTag rootTag = document != null ? document.getRootTag() : null;
|
||||
XmlFile descriptorFile = null;
|
||||
|
||||
if (notfound && // no dtd ref at all
|
||||
targetElement instanceof XmlFile &&
|
||||
deps.size() == 1 &&
|
||||
((XmlFile)targetElement).getFileType() != DTDFileType.INSTANCE
|
||||
) {
|
||||
XmlDocument document = ((XmlFile)targetElement).getDocument();
|
||||
final XmlTag rootTag = document.getRootTag();
|
||||
XmlFile descriptorFile = null;
|
||||
|
||||
if (HtmlUtil.isHtml5Document(document)) {
|
||||
descriptorFile = XmlUtil.findXmlFile((XmlFile)targetElement, Html5SchemaProvider.getCharsDtdLocation());
|
||||
} else if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) {
|
||||
final XmlElementDescriptor descriptor = rootTag.getDescriptor();
|
||||
if (HtmlUtil.isHtml5Document(document)) {
|
||||
descriptorFile = XmlUtil.findXmlFile((XmlFile)targetElement, Html5SchemaProvider.getCharsDtdLocation());
|
||||
}
|
||||
else if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) {
|
||||
final XmlElementDescriptor descriptor = rootTag.getDescriptor();
|
||||
|
||||
if (descriptor != null && !(descriptor instanceof AnyXmlElementDescriptor)) {
|
||||
PsiElement element = descriptor.getDeclaration();
|
||||
final PsiFile containingFile = element != null ? element.getContainingFile():null;
|
||||
descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile:null;
|
||||
final PsiFile containingFile = element != null ? element.getContainingFile() : null;
|
||||
descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile : null;
|
||||
}
|
||||
}
|
||||
if (descriptorFile != null &&
|
||||
!descriptorFile.getName().equals(((XmlFile)targetElement).getName() + ".dtd")) {
|
||||
deps.add(descriptorFile);
|
||||
XmlUtil.processXmlElements(
|
||||
descriptorFile,
|
||||
processor,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
if (descriptorFile != null &&
|
||||
!descriptorFile.getName().equals(((XmlFile)targetElement).getName() + ".dtd")) {
|
||||
deps.add(descriptorFile);
|
||||
XmlUtil.processXmlElements(
|
||||
descriptorFile,
|
||||
processor,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new CachedValueProvider.Result<XmlEntityDecl>(result[0], ArrayUtil.toObjectArray(deps));
|
||||
}
|
||||
finally {
|
||||
targetElement.putUserData(EVALUATION_IN_PROCESS, null);
|
||||
}
|
||||
return new CachedValueProvider.Result<XmlEntityDecl>(result[0], ArrayUtil.toObjectArray(deps));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String getDtdForEntity(XmlDoctype xmlDoctype) {
|
||||
@@ -214,7 +214,7 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef {
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiReference[] getReferences() {
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this,XmlEntityRef.class);
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user