Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-10-27 20:30:57 +03:00
190 changed files with 2540 additions and 1277 deletions
+20
View File
@@ -691,6 +691,26 @@ private String submapToXml(Map properties, List keys) {
return buff.toString()
}
private List<File> getChildren(File file) {
if (!file.isDirectory()) return []
return file.listFiles().sort { File f -> f.name.toLowerCase() }
}
binding.setVariable("getCustomJDK", { File customJdkDir ->
getChildren(customJdkDir).each {
if (it.getName().endsWith(".tar.gz")) {
def customJdkFileName = it.getAbsolutePath().substring(0, it.getAbsolutePath().length() - 3)
if (new File(customJdkFileName).exists()){ ant.delete(file: customJdkFileName) }
if (new File("${home}/build/jdk/custom_jdk_${buildNumber}.tar").exists()){
ant.delete(file: "${home}/build/jdk/custom_jdk_${buildNumber}.tar")
}
ant.gunzip(src: it.getAbsolutePath())
projectBuilder.info("customJdkFileName: " + customJdkFileName)
ant.copy(file: customJdkFileName, tofile: "${home}/build/jdk/custom_jdk_${buildNumber}.tar")
}
}
})
binding.setVariable("buildWinZip", { String zipPath, List paths ->
projectBuilder.stage(".win.zip")
@@ -73,7 +73,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jps.api.CmdlineProtoUtil;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import org.jetbrains.jps.api.RequestFuture;
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 RequestFuture 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 RequestFuture 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 RequestFuture future = compileInExternalProcess(compileContext, false);
final TaskFuture future = compileInExternalProcess(compileContext, false);
if (future != null) {
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
if (indicator.isCanceled()) {
@@ -646,7 +646,6 @@ public class CompileDriver {
final Module[] scopeModules = scope.getAffectedModules();
final List<String> modulesWithoutOutputPathSpecified = new ArrayList<String>();
final List<String> modulesWithoutJdkAssigned = new ArrayList<String>();
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
for (final Module module : scopeModules) {
if (!compilerManager.isValidationEnabled(module)) {
@@ -58,10 +58,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
@@ -112,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;
@@ -152,8 +148,10 @@ public class BuildManager implements ApplicationComponent{
private final File mySystemDirectory;
private final ProjectManager myProjectManager;
private final Map<RequestFuture, Project> myAutomakeFutures = Collections.synchronizedMap(new HashMap<RequestFuture, 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, 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>());
@@ -385,6 +383,8 @@ public class BuildManager implements ApplicationComponent{
}
public void clearState(Project project) {
cancelPreloadedBuilds(project);
final String projectPath = getProjectPath(project);
synchronized (myProjectDataMap) {
final ProjectData data = myProjectDataMap.get(projectPath);
@@ -447,7 +447,7 @@ public class BuildManager implements ApplicationComponent{
}
final List<TargetTypeBuildScope> scopes = CmdlineProtoUtil.createAllModulesScopes(false);
final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project);
final RequestFuture 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<RequestFuture> cancelAutoMakeTasks(Project project) {
final Collection<RequestFuture> futures = new SmartList<RequestFuture>();
public Collection<TaskFuture> cancelAutoMakeTasks(Project project) {
final Collection<TaskFuture> futures = new SmartList<TaskFuture>();
synchronized (myAutomakeFutures) {
for (Map.Entry<RequestFuture, Project> entry : myAutomakeFutures.entrySet()) {
for (Map.Entry<TaskFuture, Project> entry : myAutomakeFutures.entrySet()) {
if (entry.getValue().equals(project)) {
final RequestFuture future = entry.getKey();
final TaskFuture future = entry.getKey();
future.cancel(false);
futures.add(future);
}
@@ -540,211 +540,261 @@ public class BuildManager implements ApplicationComponent{
return futures;
}
private void cancelPreloadedBuilds(Project project) {
final String projectPath = getProjectPath(project);
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
getProjectData(projectPath).taskQueue.submit(new Runnable() {
@Override
public void run() {
future.waitFor();
}
});
}
}
});
}
@Nullable
public RequestFuture 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 UUID sessionId = UUID.randomUUID();
final boolean isAutomake = messageHandler instanceof AutoMakeMessageHandler;
final BuilderMessageHandler handler = new MessageHandlerWrapper(messageHandler) {
@Override
public void buildStarted(UUID sessionId) {
super.buildStarted(sessionId);
try {
ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(project, sessionId, isAutomake);
}
catch (Throwable e) {
LOG.error(e);
}
}
@Override
public void sessionTerminated(UUID sessionId) {
try {
super.sessionTerminated(sessionId);
}
finally {
try {
ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(project, sessionId, isAutomake);
}
catch (Throwable e) {
LOG.error(e);
}
}
}
};
// ensure server is listening
if (myListenPort < 0) {
try {
synchronized (this) {
if (myListenPort < 0) {
myListenPort = startListening();
}
}
}
catch (Exception e) {
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
handler.sessionTerminated(sessionId);
return null;
}
final BuilderMessageHandler handler = new NotifyingMessageHandler(project, messageHandler, messageHandler instanceof AutoMakeMessageHandler);
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<BuilderMessageHandler> future = 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 (future.isCancelled() || project.isDisposed()) {
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) {
ProjectData data = myProjectDataMap.get(projectPath);
if (data == null) {
data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
myProjectDataMap.put(projectPath, data);
}
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 (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;
}
myMessageDispatcher.registerBuildMessageHandler(sessionId, new MessageHandlerWrapper(handler) {
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 sessionTerminated(UUID sessionId) {
public void run() {
Throwable execFailure = null;
try {
super.sessionTerminated(sessionId);
}
finally {
future.setDone();
}
}
}, params);
try {
projectTaskQueue.submit(new Runnable() {
@Override
public void run() {
Throwable execFailure = null;
try {
if (project.isDisposed()) {
if (project.isDisposed()) {
if (usingPreloadedProcess) {
future.cancel(true);
}
else {
return;
}
myBuildsInProgress.put(projectPath, future);
final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, sessionId);
final StringBuilder stdErrOutput = new StringBuilder();
}
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) {
// re-translate builder's output to idea.log
final String text = event.getText();
if (!StringUtil.isEmptyOrSpaces(text)) {
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
if (stdErrOutput.length() < 1024 && ProcessOutputTypes.STDERR.equals(outputType)) {
stdErrOutput.append(text);
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 (stdErrOutput.length() > 0) {
msg.append("\n").append(stdErrOutput);
}
else {
msg.append("unknown error");
}
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
}
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 {
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
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);
}
}
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 _future;
}
return null;
@NotNull
private ProjectData getProjectData(String projectPath) {
synchronized (myProjectDataMap) {
ProjectData data = myProjectDataMap.get(projectPath);
if (data == null) {
data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
myProjectDataMap.put(projectPath, data);
}
return data;
}
}
private void ensureListening() throws Exception {
if (myListenPort < 0) {
synchronized (this) {
if (myListenPort < 0) {
myListenPort = startListening();
}
}
}
}
@Override
@@ -762,7 +812,45 @@ public class BuildManager implements ApplicationComponent{
return "com.intellij.compiler.server.BuildManager";
}
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId) throws ExecutionException {
private Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception {
ensureListening();
// 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;
}
}
});
}
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId, boolean requestProjectPreload) throws ExecutionException {
final String compilerPath;
final String vmExecutablePath;
JavaSdkVersion sdkVersion = null;
@@ -863,6 +951,11 @@ public class BuildManager implements ApplicationComponent{
}
cmdLine.addParameter("-Djdt.compiler.useSingleThread=true"); // always run eclipse compiler in single-threaded mode
if (requestProjectPreload) {
cmdLine.addParameter("-Dpreload.project.path=" + FileUtil.toCanonicalPath(getProjectPath(project)));
cmdLine.addParameter("-Dpreload.config.path=" + FileUtil.toCanonicalPath(PathManager.getOptionsPath()));
}
final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION);
if (shouldGenerateIndex != null) {
cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex);
@@ -961,12 +1054,24 @@ public class BuildManager implements ApplicationComponent{
final Process process = cmdLine.createProcess();
return new OSProcessHandler(process, null, mySystemCharset) {
final OSProcessHandler processHandler = new OSProcessHandler(process, null, mySystemCharset) {
@Override
protected boolean shouldDestroyProcessRecursively() {
return true;
}
};
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
// re-translate builder's output to idea.log
final String text = event.getText();
if (!StringUtil.isEmptyOrSpaces(text)) {
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
}
}
});
return processHandler;
}
public File getBuildSystemDirectory() {
@@ -1086,6 +1191,50 @@ public class BuildManager implements ApplicationComponent{
}
}
private static class NotifyingMessageHandler extends DelegatingMessageHandler {
private final Project myProject;
private final BuilderMessageHandler myDelegateHandler;
private boolean myIsAutomake;
public NotifyingMessageHandler(@NotNull Project project, @NotNull BuilderMessageHandler delegateHandler, final boolean isAutomake) {
myProject = project;
myDelegateHandler = delegateHandler;
myIsAutomake = isAutomake;
}
@Override
protected BuilderMessageHandler getDelegateHandler() {
return myDelegateHandler;
}
@Override
public void buildStarted(UUID sessionId) {
super.buildStarted(sessionId);
try {
ApplicationManager
.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(myProject, sessionId, myIsAutomake);
}
catch (Throwable e) {
LOG.error(e);
}
}
@Override
public void sessionTerminated(UUID sessionId) {
try {
super.sessionTerminated(sessionId);
}
finally {
try {
ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(myProject, sessionId, myIsAutomake);
}
catch (Throwable e) {
LOG.error(e);
}
}
}
}
private class ProjectWatcher extends ProjectManagerAdapter {
private final Map<Project, MessageBusConnection> myConnections = new HashMap<Project, MessageBusConnection>();
@@ -1169,7 +1318,8 @@ public class BuildManager implements ApplicationComponent{
@Override
public void projectClosing(Project project) {
for (RequestFuture future : cancelAutoMakeTasks(project)) {
cancelPreloadedBuilds(project);
for (TaskFuture future : cancelAutoMakeTasks(project)) {
future.waitFor(500, TimeUnit.MILLISECONDS);
}
}
@@ -1185,13 +1335,14 @@ public class BuildManager implements ApplicationComponent{
}
private static class ProjectData {
@NotNull
final SequentialTaskExecutor taskQueue;
private final Set<InternedPath> myChanged = new THashSet<InternedPath>();
private final Set<InternedPath> myDeleted = new THashSet<InternedPath>();
private long myNextEventOrdinal = 0L;
private boolean myNeedRescan = true;
private ProjectData(SequentialTaskExecutor taskQueue) {
private ProjectData(@NotNull SequentialTaskExecutor taskQueue) {
this.taskQueue = taskQueue;
}
@@ -1328,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);
}
}
}
@@ -21,10 +21,12 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.io.SimpleChannelInboundHandlerAdapter;
import org.jetbrains.jps.api.CmdlineProtoUtil;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import org.jetbrains.jps.api.RequestFuture;
import java.util.Map;
import java.util.Set;
@@ -41,19 +43,34 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
private static final AttributeKey<SessionData> SESSION_DATA = AttributeKey.valueOf("BuildMessageDispatcher.sessionData");
private final Map<UUID, SessionData> myMessageHandlers = new ConcurrentHashMap<UUID, SessionData>(16, 0.75f, 1);
private final Map<UUID, SessionData> mySessionDescriptors = new ConcurrentHashMap<UUID, SessionData>(16, 0.75f, 1);
private final Set<UUID> myCanceledSessions = new ConcurrentHashSet<UUID>();
public void registerBuildMessageHandler(UUID sessionId,
BuilderMessageHandler handler,
CmdlineRemoteProto.Message.ControllerMessage params) {
myMessageHandlers.put(sessionId, new SessionData(sessionId, handler, params));
public void registerBuildMessageHandler(@NotNull final RequestFuture<? extends BuilderMessageHandler> future, @Nullable CmdlineRemoteProto.Message.ControllerMessage params) {
final BuilderMessageHandler wrappedHandler = new DelegatingMessageHandler() {
@Override
protected BuilderMessageHandler getDelegateHandler() {
return future.getMessageHandler();
}
@Override
public void sessionTerminated(UUID sessionId) {
try {
super.sessionTerminated(sessionId);
}
finally {
future.setDone();
}
}
};
final UUID sessionId = future.getRequestID();
mySessionDescriptors.put(sessionId, new SessionData(sessionId, wrappedHandler, params));
}
@Nullable
public BuilderMessageHandler unregisterBuildMessageHandler(UUID sessionId) {
myCanceledSessions.remove(sessionId);
final SessionData data = myMessageHandlers.remove(sessionId);
final SessionData data = mySessionDescriptors.remove(sessionId);
return data != null? data.handler : null;
}
@@ -74,11 +91,36 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
@Nullable
public Channel getAssociatedChannel(final UUID sessionId) {
final SessionData data = myMessageHandlers.get(sessionId);
final SessionData data = mySessionDescriptors.get(sessionId);
return data != null? data.channel : null;
}
public boolean sendBuildParameters(@NotNull final UUID preloadedSessionId, @NotNull CmdlineRemoteProto.Message.ControllerMessage params) {
boolean succeeded = false;
final SessionData sessionData = mySessionDescriptors.get(preloadedSessionId);
if (sessionData != null) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (sessionData) {
if (sessionData.state == SessionData.State.WAITING_PARAMS) {
sessionData.state = SessionData.State.RUNNING;
final Channel channel = sessionData.channel;
if (channel != null && channel.isActive()) {
sessionData.handler.buildStarted(preloadedSessionId);
channel.writeAndFlush(CmdlineProtoUtil.toMessage(preloadedSessionId, params));
succeeded = true;
}
}
else {
if (sessionData.state == SessionData.State.INITIAL) {
sessionData.params = params;
succeeded = true;
}
}
}
}
return succeeded;
}
@Override
protected void messageReceived(ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
SessionData sessionData = context.attr(SESSION_DATA).get();
@@ -89,7 +131,7 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
final CmdlineRemoteProto.Message.UUID id = message.getSessionId();
sessionId = new UUID(id.getMostSigBits(), id.getLeastSigBits());
sessionData = myMessageHandlers.get(sessionId);
sessionData = mySessionDescriptors.get(sessionId);
if (sessionData != null) {
sessionData.channel = context.channel();
context.attr(SESSION_DATA).set(sessionData);
@@ -119,14 +161,25 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
final CmdlineRemoteProto.Message.BuilderMessage builderMessage = message.getBuilderMessage();
final CmdlineRemoteProto.Message.BuilderMessage.Type msgType = builderMessage.getType();
if (msgType == CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST) {
final CmdlineRemoteProto.Message.ControllerMessage params = sessionData.params;
if (params != null) {
handler.buildStarted(sessionId);
sessionData.params = null;
context.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, params));
}
else {
cancelSession(sessionId);
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (sessionData) {
final CmdlineRemoteProto.Message.ControllerMessage params = sessionData.params;
if (params != null) {
sessionData.state = SessionData.State.RUNNING;
handler.buildStarted(sessionId);
sessionData.params = null;
context.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, params));
}
else {
if (sessionData.state == SessionData.State.INITIAL) {
sessionData.state = SessionData.State.WAITING_PARAMS;
}
else {
// this message is expected to be sent only once.
// To be on the safe side, cancel the session
cancelSession(sessionId);
}
}
}
}
else {
@@ -165,12 +218,19 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
}
private static final class SessionData {
enum State {
INITIAL, WAITING_PARAMS, RUNNING
}
@NotNull
final UUID sessionId;
@NotNull
final BuilderMessageHandler handler;
volatile CmdlineRemoteProto.Message.ControllerMessage params;
volatile Channel channel;
State state = State.INITIAL;
private SessionData(UUID sessionId, BuilderMessageHandler handler, CmdlineRemoteProto.Message.ControllerMessage params) {
private SessionData(@NotNull UUID sessionId, @NotNull BuilderMessageHandler handler, CmdlineRemoteProto.Message.ControllerMessage params) {
this.sessionId = sessionId;
this.handler = handler;
this.params = params;
@@ -25,6 +25,24 @@ import java.util.UUID;
* Date: 4/25/12
*/
public interface BuilderMessageHandler {
BuilderMessageHandler DEAF = new BuilderMessageHandler() {
@Override
public void buildStarted(UUID sessionId) {
}
@Override
public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
}
@Override
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
}
@Override
public void sessionTerminated(UUID sessionId) {
}
};
void buildStarted(UUID sessionId);
void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg);
@@ -9,30 +9,27 @@ import java.util.UUID;
* @author Eugene Zhuravlev
* Date: 7/3/13
*/
class MessageHandlerWrapper implements BuilderMessageHandler {
private final BuilderMessageHandler myHandler;
abstract class DelegatingMessageHandler implements BuilderMessageHandler {
public MessageHandlerWrapper(BuilderMessageHandler handler) {
myHandler = handler;
}
protected abstract BuilderMessageHandler getDelegateHandler();
@Override
public void buildStarted(UUID sessionId) {
myHandler.buildStarted(sessionId);
getDelegateHandler().buildStarted(sessionId);
}
@Override
public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
myHandler.handleBuildMessage(channel, sessionId, msg);
getDelegateHandler().handleBuildMessage(channel, sessionId, msg);
}
@Override
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
myHandler.handleFailure(sessionId, failure);
getDelegateHandler().handleFailure(sessionId, failure);
}
@Override
public void sessionTerminated(UUID sessionId) {
myHandler.sessionTerminated(sessionId);
getDelegateHandler().sessionTerminated(sessionId);
}
}
@@ -0,0 +1,48 @@
/*
* 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.compiler.server;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Eugene Zhuravlev
* Date: 20-Oct-14
*/
class PreloadedProcessMessageHandler extends DelegatingMessageHandler {
@NotNull
private final Project myProject;
private volatile BuilderMessageHandler myDelegateHandler;
public PreloadedProcessMessageHandler(@NotNull Project project) {
myProject = project;
}
@NotNull
public Project getProject() {
return myProject;
}
@Override
protected BuilderMessageHandler getDelegateHandler() {
final BuilderMessageHandler delegate = myDelegateHandler;
return delegate != null? delegate : BuilderMessageHandler.DEAF;
}
public void setDelegateHandler(BuilderMessageHandler delegateHandler) {
myDelegateHandler = delegateHandler;
}
}
@@ -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) {
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.codeInsight.intention.HighPriorityAction;
@@ -208,6 +209,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (element instanceof PsiNewExpression) {
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
LOG.assertTrue(anonymousClass != null);
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -115,6 +116,7 @@ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalI
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (element instanceof PsiNewExpression) {
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
if (anonymousClass == null) return;
final PsiMethod[] methods = anonymousClass.getMethods();
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -94,7 +95,9 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaBatchLocalInspec
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiDiamondTypeUtil.replaceExplicitWithDiamond(descriptor.getPsiElement());
final PsiElement element = descriptor.getPsiElement();
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
PsiDiamondTypeUtil.replaceExplicitWithDiamond(element);
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -390,6 +391,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
if (lambdaExpression == null) return;
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
@@ -16,6 +16,7 @@
package com.intellij.codeInspection;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
@@ -133,6 +134,7 @@ public class PossibleHeapPollutionVarargsInspection extends BaseJavaBatchLocalIn
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement instanceof PsiIdentifier) {
if (!FileModificationService.getInstance().preparePsiElementForWrite(psiElement)) return;
final PsiMethod psiMethod = (PsiMethod)psiElement.getParent();
psiMethod.getModifierList().setModifierProperty(PsiModifier.FINAL, true);
new AddAnnotationPsiFix("java.lang.SafeVarargs", psiMethod, PsiNameValuePair.EMPTY_ARRAY).applyFix(project, descriptor);
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -158,6 +159,7 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaBatchLocalInspec
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (element != null) {
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
if (lambdaExpression != null) {
final PsiElement body = lambdaExpression.getBody();
@@ -92,12 +92,28 @@ public class ExtractLightMethodObjectHandler {
final TextRange range = originalContext.getTextRange();
final PsiElement originalAnchor =
CodeInsightUtil.findElementInRange(copy, range.getStartOffset(), range.getEndOffset(), originalContext.getClass());
//todo before this or super, not found etc
final PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false);
if (anchor == null) {
final PsiClass containingClass = PsiTreeUtil.getParentOfType(originalAnchor, PsiClass.class);
if (containingClass == null) {
return null;
}
final PsiElement container = anchor.getParent();
PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false);
if (anchor == null) {
if (PsiTreeUtil.getParentOfType(originalAnchor, PsiCodeBlock.class) != null) {
anchor = originalAnchor;
}
}
final PsiElement container;
if (anchor == null) {
container = ((PsiClassInitializer)containingClass.add(elementFactory.createClassInitializer())).getBody();
anchor = container.getLastChild();
}
else {
container = anchor.getParent();
}
final PsiElement firstElementCopy = container.addRangeBefore(elements[0], elements[elements.length - 1], anchor);
final PsiElement[] elementsCopy = CodeInsightUtil.findStatementsInRange(copy,
firstElementCopy.getTextRange().getStartOffset(),
@@ -870,32 +870,38 @@ public class RefactoringUtil {
JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);
if (loopBodyCopy != null) codeBlock.add(loopBodyCopy);
} else if (container instanceof PsiLambdaExpression) {
final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)container;
final PsiElement lambdaExpressionBody = lambdaExpression.getBody();
LOG.assertTrue(lambdaExpressionBody != null);
PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)container;
final PsiElement invalidBody = lambdaExpression.getBody();
if (invalidBody == null) return declaration;
final PsiLambdaExpression expressionFromText = (PsiLambdaExpression)elementFactory
.createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression);
.createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression.getParent());
PsiCodeBlock newBody = (PsiCodeBlock)expressionFromText.getBody();
LOG.assertTrue(newBody != null);
newBody.add(declaration);
PsiStatement lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression);
((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody);
lambdaExpression =
(PsiLambdaExpression)lambdaExpression.replace(elementFactory.createExpressionFromText(
lambdaExpression.getParameterList().getText() + " -> " + invalidBody.getText(), lambdaExpression));
final PsiElement lambdaExpressionBody = lambdaExpression.getBody();
LOG.assertTrue(lambdaExpressionBody != null);
final PsiStatement lastBodyStatement;
if (LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression) == PsiType.VOID) {
lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression);
((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody);
}
else {
lastBodyStatement = elementFactory.createStatementFromText("return a;", lambdaExpression);
final PsiExpression returnValue = ((PsiReturnStatement)lastBodyStatement).getReturnValue();
LOG.assertTrue(returnValue != null);
returnValue.replace(lambdaExpressionBody);
}
newBody.add(lastBodyStatement);
PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText);
final PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText);
newBody = (PsiCodeBlock)copy.getBody();
LOG.assertTrue(newBody != null);
if (LambdaUtil.getFunctionalInterfaceReturnType(copy) != PsiType.VOID) {
PsiExpressionStatement lastStatement = (PsiExpressionStatement)newBody.getStatements()[1];
PsiReturnStatement returnStatement = (PsiReturnStatement)elementFactory.createStatementFromText("return a;", copy);
final PsiExpression returnValue = returnStatement.getReturnValue();
LOG.assertTrue(returnValue != null);
returnValue.replace(lastStatement.getExpression());
lastStatement.replace(returnStatement);
}
declaration = newBody.getStatements()[0];
declaration = (PsiStatement)JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);
}
@@ -0,0 +1,10 @@
class Sample {
void a() {
System.out.println("");
<caret>}
private int foo() {
return 1;
}
}
@@ -0,0 +1,12 @@
class Sample {
void a() {
class Local {
<caret>}
}
private int foo() {
return 1;
}
}
@@ -0,0 +1,7 @@
class Sample {
static {<caret>}
int foo() {
return 1;
}
}
@@ -0,0 +1,7 @@
class Sample {
int <caret>i = 0;
int foo() {
return 1;
}
}
@@ -0,0 +1,9 @@
class Sample {
public Sample() {
<caret>super();
}
int foo() {
return 1;
}
}
@@ -0,0 +1,20 @@
class Foo {
interface I<T> {
T m(Object op);
}
interface J<T> {
void m(T o);
}
void f(J r) {}
void f(I<String> r) {}
{
f((a) -> {
int c = 1;
return c;
});
}
}
@@ -0,0 +1,17 @@
class Foo {
interface I<T> {
T m(Object op);
}
interface J<T> {
void m(T o);
}
void f(J r) {}
void f(I<String> r) {}
{
f((a) -> <selection>1</selection>);
}
}
@@ -214,6 +214,56 @@ public class ExtractMethodObject4DebuggerTest extends LightRefactoringTestCase {
" }", false);
}
public void testOnClosingBrace() throws Exception {
doTest(" foo()", "int result = new Test().invoke();",
"public class Test {\n" +
" public int invoke() {\n" +
" return foo();\n" +
" }\n" +
" }");
}
public void testOnClosingBraceLocalClass() throws Exception {
doTest(" foo()", "int result = new Test().invoke();",
"public class Test {\n" +
" public int invoke() {\n" +
" return foo();\n" +
" }\n" +
" }");
}
public void testOnFieldInitialization() throws Exception {
doTest(" foo()", "int result = new Test().invoke();",
"public class Test {\n" +
" public int invoke() {\n" +
" return foo();\n" +
" }\n" +
" }");
}
public void testOnEmptyMethod() throws Exception {
doTest(" foo()", "int result = Test.invoke();",
"public static class Test {\n" +
" public static int invoke() {\n" +
" return foo();\n" +
" }\n" +
" }");
}
public void testOnSuperConstructorCall() throws Exception {
doTest(" foo()", "int result = new Test().invoke();",
"public class Test {\n" +
" public int invoke() {\n" +
" return foo();\n" +
" }\n" +
" }");
}
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk18();
@@ -441,6 +441,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
doTest(new MockIntroduceVariableHandler("c", false, false, false, "int"));
}
public void testPutInLambdaBodyVoidValueConflict() {
doTest(new MockIntroduceVariableHandler("c", false, false, false, "int"));
}
public void testNormalizeDeclarations() {
doTest(new MockIntroduceVariableHandler("i3", false, false, false, "int"));
}
@@ -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;
@@ -35,7 +36,11 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.api.CmdlineProtoUtil;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.incremental.MessageHandler;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.fs.FSState;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.*;
@@ -49,6 +54,9 @@ import java.util.concurrent.TimeUnit;
*/
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public class BuildMain {
private static final String PRELOAD_PROJECT_PATH = "preload.project.path";
private static final String PRELOAD_CONFIG_PATH = "preload.config.path";
private static final String LOG_CONFIG_FILE_NAME = "build-log.xml";
private static final String LOG_FILE_NAME = "build.log";
private static final String DEFAULT_LOGGER_CONFIG = "defaultLogConfig.xml";
@@ -65,19 +73,10 @@ public class BuildMain {
private static final int SYSTEM_DIR_ARG = SESSION_ID_ARG + 1;
private static NioEventLoopGroup ourEventLoopGroup;
@Nullable
private static PreloadedData ourPreloadedData;
public static void main(String[] args){
final long start = System.nanoTime();
Runtime.getRuntime().addShutdownHook(new Thread("TimeLogger"){
public void run() {
final long totalTime = (System.nanoTime() - start) / 1000000L;
final long millis = totalTime % 1000L ;
final long seconds = totalTime / 1000L;
LOG.info("Total build time " + seconds + " sec " + millis + " ms");
}
});
System.out.println("Build process started. Classpath: " + System.getProperty("java.class.path"));
final String host = args[HOST_ARG];
final int port = Integer.parseInt(args[PORT_ARG]);
@@ -123,6 +122,60 @@ public class BuildMain {
final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)).awaitUninterruptibly();
final boolean success = future.isSuccess();
if (success) {
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);
final File dataStorageRoot = Utils.getDataStorageRoot(projectPathToPreload);
final BuildFSState fsState = new BuildFSState(false);
final ProjectDescriptor pd = runner.load(new MessageHandler() {
@Override
public void processMessage(BuildMessage msg) {
data.addMessage(msg);
}
}, dataStorageRoot, fsState);
data.setProjectDescriptor(pd);
try {
final File fsStateFile = new File(dataStorageRoot, BuildSession.FS_STATE_FILE);
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fsStateFile)));
try {
final int version = in.readInt();
if (version == FSState.VERSION) {
final long savedOrdinal = in.readLong();
in.readBoolean(); // must skip "has-work-to-do" flag
fsState.load(in, pd.getModel(), pd.getBuildRootIndex());
data.setFsEventOrdinal(savedOrdinal);
}
}
finally {
in.close();
}
}
catch (FileNotFoundException ignored) {
}
catch (IOException e) {
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
}
}
else if (projectPathToPreload != null || globalsPathToPreload != null){
LOG.info("Skipping project pre-loading step: both paths to project configuration files and path to global settings must be specified");
}
future.channel().writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createParamRequest()));
}
else {
@@ -159,7 +212,7 @@ public class BuildMain {
case BUILD_PARAMETERS: {
if (mySession == null) {
final CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta = controllerMessage.hasFsEvent()? controllerMessage.getFsEvent() : null;
final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta);
final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta, ourPreloadedData);
mySession = session;
SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
@Override
@@ -58,14 +58,20 @@ public class BuildRunner {
public static final boolean PARALLEL_BUILD_ENABLED = Boolean.parseBoolean(System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "false"));
private static final boolean STORE_TEMP_CACHES_IN_MEMORY = PARALLEL_BUILD_ENABLED || Boolean.valueOf(System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION, "true"));
private final JpsModelLoader myModelLoader;
private final List<String> myFilePaths;
private final Map<String, String> myBuilderParams;
private List<String> myFilePaths = Collections.emptyList();
private Map<String, String> myBuilderParams = Collections.emptyMap();
private boolean myForceCleanCaches;
public BuildRunner(JpsModelLoader modelLoader, List<String> filePaths, Map<String, String> builderParams) {
public BuildRunner(JpsModelLoader modelLoader) {
myModelLoader = modelLoader;
myFilePaths = filePaths;
myBuilderParams = builderParams;
}
public void setFilePaths(List<String> filePaths) {
myFilePaths = filePaths != null? filePaths : Collections.<String>emptyList();
}
public void setBuilderParams(Map<String, String> builderParams) {
myBuilderParams = builderParams != null? builderParams : Collections.<String, String>emptyMap();
}
public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException {
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.concurrency.SequentialTaskExecutor;
import com.intellij.util.io.DataOutputStream;
import io.netty.channel.Channel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.TimingLog;
import org.jetbrains.jps.api.*;
@@ -57,9 +58,11 @@ import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage
*/
final class BuildSession implements Runnable, CanceledStatus {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildSession");
private static final String FS_STATE_FILE = "fs_state.dat";
public static final String FS_STATE_FILE = "fs_state.dat";
private final UUID mySessionId;
private final Channel myChannel;
@Nullable
private final PreloadedData myPreloadedData;
private volatile boolean myCanceled = false;
private final String myProjectPath;
@Nullable
@@ -70,6 +73,7 @@ final class BuildSession implements Runnable, CanceledStatus {
private volatile ProjectDescriptor myProjectDescriptor;
private final Map<Pair<String, String>, ConstantSearchFuture> mySearchTasks = Collections.synchronizedMap(new HashMap<Pair<String, String>, ConstantSearchFuture>());
private final ConstantSearch myConstantSearch = new ConstantSearch();
@NotNull
private final BuildRunner myBuildRunner;
private final boolean myForceModelLoading;
private final BuildType myBuildType;
@@ -78,24 +82,31 @@ final class BuildSession implements Runnable, CanceledStatus {
BuildSession(UUID sessionId,
Channel channel,
CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage params,
@Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta) {
@Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta, @Nullable PreloadedData preloaded) {
mySessionId = sessionId;
myChannel = channel;
myPreloadedData = preloaded;
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = params.getGlobalSettings();
myProjectPath = FileUtil.toCanonicalPath(params.getProjectId());
String globalOptionsPath = FileUtil.toCanonicalPath(globals.getGlobalOptionsPath());
myBuildType = convertCompileType(params.getBuildType());
myScopes = params.getScopeList();
List<String> filePaths = params.getFilePathList();
Map<String, String> builderParams = new HashMap<String, String>();
final Map<String, String> builderParams = new HashMap<String, String>();
for (CmdlineRemoteProto.Message.KeyValuePair pair : params.getBuilderParameterList()) {
builderParams.put(pair.getKey(), pair.getValue());
}
myInitialFSDelta = delta;
JpsModelLoaderImpl loader = new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null);
myForceModelLoading = Boolean.parseBoolean(builderParams.get(BuildParametersKeys.FORCE_MODEL_LOADING));
myBuildRunner = new BuildRunner(loader, filePaths, builderParams);
if (preloaded == null || preloaded.getRunner() == null) {
myBuildRunner = new BuildRunner(new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null));
}
else {
myBuildRunner = preloaded.getRunner();
}
myBuildRunner.setFilePaths(filePaths);
myBuildRunner.setBuilderParams(builderParams);
myForceModelLoading = (preloaded != null && preloaded.getProjectDescriptor() != null) || Boolean.parseBoolean(builderParams.get(BuildParametersKeys.FORCE_MODEL_LOADING));
}
@Override
@@ -185,8 +196,9 @@ final class BuildSession implements Runnable, CanceledStatus {
// invoked the very first time for this project
myBuildRunner.setForceCleanCaches(true);
}
final DataInputStream fsStateStream = createFSDataStream(dataStorageRoot);
final ProjectDescriptor preloadedProject = myPreloadedData != null? myPreloadedData.getProjectDescriptor() : null;
final DataInputStream fsStateStream =
preloadedProject != null || myInitialFSDelta == null /*this will force FS rescan*/? null : createFSDataStream(dataStorageRoot, myInitialFSDelta.getOrdinal());
if (fsStateStream != null) {
// optimization: check whether we can skip the build
@@ -198,27 +210,56 @@ final class BuildSession implements Runnable, CanceledStatus {
}
}
final BuildFSState fsState = new BuildFSState(false);
final BuildFSState fsState = preloadedProject != null? preloadedProject.fsState : new BuildFSState(false);
try {
final ProjectDescriptor pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState);
TimingLog.LOG.debug("Project descriptor loaded");
myProjectDescriptor = pd;
if (fsStateStream != null) {
try {
try {
fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex());
applyFSEvent(pd, myInitialFSDelta, false);
TimingLog.LOG.debug("FS Delta loaded");
}
finally {
fsStateStream.close();
final ProjectDescriptor pd;
if (preloadedProject != null) {
pd = preloadedProject;
final List<BuildMessage> preloadMessages = myPreloadedData.getLoadMessages();
if (!preloadMessages.isEmpty()) {
// replay preload-time messages, so that they are delivered to the IDE
for (BuildMessage message : preloadMessages) {
msgHandler.processMessage(message);
}
}
catch (Throwable e) {
LOG.error(e);
fsState.clearAll();
if (myInitialFSDelta == null || myPreloadedData.getFsEventOrdinal() + 1L != myInitialFSDelta.getOrdinal()) {
// FS rescan was forced
fsState.clearAll();
}
else {
// apply events to already loaded state
try {
applyFSEvent(pd, myInitialFSDelta, false);
}
catch (Throwable e) {
LOG.error(e);
fsState.clearAll();
}
}
}
else {
// standard case
pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState);
TimingLog.LOG.debug("Project descriptor loaded");
if (fsStateStream != null) {
try {
try {
fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex());
applyFSEvent(pd, myInitialFSDelta, false);
TimingLog.LOG.debug("FS Delta loaded");
}
finally {
fsStateStream.close();
}
}
catch (Throwable e) {
LOG.error(e);
fsState.clearAll();
}
}
}
myProjectDescriptor = pd;
myLastEventOrdinal = myInitialFSDelta != null? myInitialFSDelta.getOrdinal() : 0L;
// free memory
@@ -469,11 +510,7 @@ final class BuildSession implements Runnable, CanceledStatus {
}
@Nullable
private DataInputStream createFSDataStream(File dataStorageRoot) {
if (myInitialFSDelta == null) {
// this will force FS rescan
return null;
}
private static DataInputStream createFSDataStream(File dataStorageRoot, final long currentEventOrdinal) {
try {
final File file = new File(dataStorageRoot, FS_STATE_FILE);
byte[] bytes;
@@ -490,7 +527,7 @@ final class BuildSession implements Runnable, CanceledStatus {
return null;
}
final long savedOrdinal = in.readLong();
if (savedOrdinal + 1L != myInitialFSDelta.getOrdinal()) {
if (savedOrdinal + 1L != currentEventOrdinal) {
return null;
}
return in;
@@ -0,0 +1,71 @@
/*
* 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.cmdline;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eugene Zhuravlev
* Date: 22-Oct-14
*/
public class PreloadedData {
@Nullable
private BuildRunner runner;
@Nullable
private ProjectDescriptor projectDescriptor;
private final List<BuildMessage> loadMessages = new ArrayList<BuildMessage>();
private long fsEventOrdinal;
@Nullable
public BuildRunner getRunner() {
return runner;
}
public void setRunner(@Nullable BuildRunner runner) {
this.runner = runner;
}
@Nullable
public ProjectDescriptor getProjectDescriptor() {
return projectDescriptor;
}
public void setProjectDescriptor(@Nullable ProjectDescriptor projectDescriptor) {
this.projectDescriptor = projectDescriptor;
}
public long getFsEventOrdinal() {
return fsEventOrdinal;
}
public void setFsEventOrdinal(long fsEventOrdinal) {
this.fsEventOrdinal = fsEventOrdinal;
}
public List<BuildMessage> getLoadMessages() {
return loadMessages;
}
public void addMessage(BuildMessage msg) {
loadMessages.add(msg);
}
}
@@ -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());
@@ -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");
}
@@ -193,8 +193,7 @@ public class Standalone {
public static void runBuild(JpsModelLoader loader, File dataStorageRoot, MessageHandler messageHandler, List<TargetTypeBuildScope> scopes,
boolean includeDependenciesToScope) throws Exception {
final BuildRunner buildRunner = new BuildRunner(loader, Collections.<String>emptyList(), Collections.<String, String>emptyMap()
);
final BuildRunner buildRunner = new BuildRunner(loader);
ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true));
try {
buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, BuildType.BUILD, scopes, includeDependenciesToScope);
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
class FCTSBackedLighterAST extends LighterAST {
public class FCTSBackedLighterAST extends LighterAST {
private final FlyweightCapableTreeStructure<LighterASTNode> myTreeStructure;
public FCTSBackedLighterAST(final CharTable charTable, final FlyweightCapableTreeStructure<LighterASTNode> treeStructure) {
@@ -17,6 +17,7 @@ package com.intellij.lang;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Top-level node in AST, corresponds to PsiFile.
@@ -28,4 +29,7 @@ public interface FileASTNode extends ASTNode {
CharTable getCharTable();
boolean isParsed();
@Nullable
LighterAST getLighterAST();
}
@@ -15,8 +15,6 @@
*/
package com.intellij.lang;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.ILightStubFileElementType;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,19 +44,4 @@ public abstract class LighterAST {
@NotNull
public abstract List<LighterASTNode> getChildren(@NotNull final LighterASTNode parent);
public static @Nullable LighterAST getLighterASTFromFileAST(@NotNull FileASTNode node, @NotNull Language language) {
final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType();
assert contentType instanceof ILightStubFileElementType;
final LighterAST tree;
if (!node.isParsed()) {
final ILightStubFileElementType<?> type = (ILightStubFileElementType)contentType;
tree = new FCTSBackedLighterAST(node.getCharTable(), type.parseContentsLight(node));
}
else {
tree = new TreeBackedLighterAST(node);
}
return tree;
}
}
@@ -47,7 +47,7 @@ public class LightStubBuilder implements StubBuilder {
LOG.error("File is not of ILightStubFileElementType: " + contentType + ", " + file);
return null;
}
final LighterAST tree = LighterAST.getLighterASTFromFileAST(file.getNode(), language);
final LighterAST tree = file.getNode().getLighterAST();
if (tree == null) return null;
final StubElement rootStub = createStubForFile(file, tree);
@@ -30,7 +30,10 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.PlatformUtilsCore;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.execution.ParametersListUtil;
@@ -166,7 +169,7 @@ public class PluginManagerCore {
return app != null && app.isUnitTestMode();
}
public static void savePluginsList(Collection<String> ids, boolean append, File plugins) throws IOException {
public static void savePluginsList(@NotNull Collection<String> ids, boolean append, @NotNull File plugins) throws IOException {
if (!plugins.isFile()) {
FileUtil.ensureCanCreateFile(plugins);
}
@@ -700,7 +703,13 @@ public class PluginManagerCore {
List<IdeaPluginDescriptorImpl> result,
@Nullable StartupProgress progress,
int pluginsCount) {
final File pluginsHome = new File(pluginsPath);
loadDescriptors(new File(pluginsPath), result, progress, pluginsCount);
}
public static void loadDescriptors(@NotNull File pluginsHome,
List<IdeaPluginDescriptorImpl> result,
@Nullable StartupProgress progress,
int pluginsCount) {
final File[] files = pluginsHome.listFiles();
if (files != null) {
int i = result.size();
@@ -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;
}
@@ -16,16 +16,19 @@
package com.intellij.psi.impl.source.tree;
import com.intellij.lang.ASTNode;
import com.intellij.lang.FileASTNode;
import com.intellij.lang.*;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.CharTableImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.ILightStubFileElementType;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class FileElement extends LazyParseableElement implements FileASTNode, Getter<FileElement> {
private volatile CharTable myCharTable = new CharTableImpl();
@@ -47,6 +50,35 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge
return myCharTable;
}
private static final Key<LighterAST> ourTreeKey = Key.create("lighter.key");
@Nullable
@Override
public LighterAST getLighterAST() {
final IFileElementType contentType = (IFileElementType)getElementType();
assert contentType instanceof ILightStubFileElementType;
LighterAST tree;
if (!isParsed()) {
tree = getUserData(ourTreeKey);
if (tree == null) {
final ILightStubFileElementType<?> type = (ILightStubFileElementType)contentType;
tree = new FCTSBackedLighterAST(getCharTable(), type.parseContentsLight(this));
putUserData(ourTreeKey, tree);
}
}
else {
tree = new TreeBackedLighterAST(this);
}
return tree;
}
@Override
protected void resetCachesOnParsedStateUpdate() {
putUserData(ourTreeKey, null);
super.resetCachesOnParsedStateUpdate();
}
public FileElement(IElementType type, CharSequence text) {
super(type, text);
}
@@ -181,8 +181,8 @@ public class LazyParseableElement extends CompositeElement {
if (rawFirstChild() != null) {
LOG.error("Reentrant parsing?");
}
myText = null;
resetCachesOnParsedStateUpdate();
if (parsedNode == null) return;
super.rawAddChildrenWithoutNotifications((TreeElement)parsedNode);
@@ -199,6 +199,10 @@ public class LazyParseableElement extends CompositeElement {
}
}
protected void resetCachesOnParsedStateUpdate() {
myText = null;
}
@Override
public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) {
if (myText() != null) {
@@ -0,0 +1,31 @@
/*
* 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.dupLocator;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.psi.PsiFile;
/**
* Created by Maxim.Mossienko on 10/1/2014.
*/
public interface LightDuplicateProfile {
void process(PsiFile file, Callback callback);
interface Callback {
void process(LighterAST ast, LighterASTNode node, int hash);
}
}
@@ -18,15 +18,18 @@ package com.intellij.dupLocator.index;
import com.intellij.dupLocator.DuplicatesProfile;
import com.intellij.dupLocator.DuplocateVisitor;
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.Language;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.util.SystemProperties;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
@@ -52,6 +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 = true;
private static boolean isEnabledByDefault() {
Application application = ApplicationManager.getApplication();
@@ -59,7 +63,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
}
@NonNls public static final ID<Integer, TIntArrayList> NAME = ID.create("DuplicatesIndex");
private static final int myBaseVersion = 10;
private static final int myBaseVersion = 12;
private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
@Override
@@ -107,21 +111,31 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
@Override
@NotNull
public Map<Integer, TIntArrayList> map(@NotNull final FileContent inputData) {
return ApplicationManager.getApplication().runReadAction(new Computable<Map<Integer, TIntArrayList>>() {
@Override
public Map<Integer, TIntArrayList> compute() {
FileType type = inputData.getFileType();
FileType type = inputData.getFileType();
DuplicatesProfile profile = findDuplicatesProfile(type);
if (profile == null) return Collections.emptyMap();
DuplicatesProfile profile = findDuplicatesProfile(type);
if (profile == null) return Collections.emptyMap();
MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage());
DuplocateVisitor visitor = profile.createVisitor(collector, true);
visitor.visitNode(((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument());
PsiFile psiFile = ((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument();
return collector.getMap();
}
});
if (profile instanceof LightDuplicateProfile && ourEnabledLightProfiles) {
final THashMap<Integer, TIntArrayList> result = new THashMap<Integer, TIntArrayList>();
((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() {
@Override
public void process(LighterAST ast, LighterASTNode node, int hash) {
TIntArrayList list = result.get(hash);
if (list == null) { result.put(hash, list = new TIntArrayList(1)); }
list.add(node.getStartOffset());
}
});
return result;
}
MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage());
DuplocateVisitor visitor = profile.createVisitor(collector, true);
visitor.visitNode(psiFile);
return collector.getMap();
}
};
@@ -135,7 +149,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
@Override
public int getVersion() {
return myBaseVersion + (ourEnabled ? 0xFF : 0);
return myBaseVersion + (ourEnabled ? 0xFF : 0) + (ourEnabledLightProfiles ? 0x7F : 0);
}
@Override
@@ -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);
}
}
@@ -38,6 +38,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Key;
@@ -421,7 +422,11 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
//Stage two: try to get content from descriptor itself
final Content attachedContent = descriptor.getAttachedContent();
if (attachedContent != null && attachedContent.isValid() && contentManager.getIndexOfContent(attachedContent) != -1) {
if (attachedContent != null
&& attachedContent.isValid()
&& contentManager.getIndexOfContent(attachedContent) != -1
&& (Comparing.equal(descriptor.getDisplayName(), attachedContent.getDisplayName()) || !attachedContent.isPinned())) {
content = attachedContent;
}
}
@@ -321,9 +321,13 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
@Override
public Comparable getTypeSortKey() {
VirtualFile file = getVirtualFile();
if (file == null) return null;
String extension = file.getExtension();
return extension == null ? null : new PsiFileNode.ExtensionSortKey(extension);
if (file != null) {
String extension = file.getExtension();
if (extension != null) {
return new PsiFileNode.ExtensionSortKey(extension);
}
}
return null;
}
@Override
@@ -17,11 +17,14 @@ package com.intellij.openapi.application;
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.AppUIUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -30,8 +33,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.PropertyResourceBundle;
@@ -55,21 +56,25 @@ public class ConfigImportHelper {
private ConfigImportHelper() {
}
public static void importConfigsTo(String newConfigPath) {
public static void importConfigsTo(@NotNull String newConfigPath) {
ConfigImportSettings settings = getConfigImportSettings();
File oldConfigDir = findOldConfigDir(newConfigPath, settings.getCustomPathsSelector());
File newConfigDir = new File(newConfigPath);
File oldConfigDir = findOldConfigDir(newConfigDir, settings.getCustomPathsSelector());
do {
ImportOldConfigsPanel dialog = new ImportOldConfigsPanel(oldConfigDir, settings);
dialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL);
AppUIUtil.updateWindowIcon(dialog);
dialog.setVisible(true);
if (dialog.isImportEnabled()) {
File instHome = dialog.getSelectedFile();
oldConfigDir = getOldConfigDir(instHome, settings);
if (!validateOldConfigDir(instHome, oldConfigDir, settings)) continue;
File installationHome = dialog.getSelectedFile();
oldConfigDir = getOldConfigDir(installationHome, settings);
if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) {
continue;
}
doImport(newConfigPath, oldConfigDir);
assert oldConfigDir != null;
doImport(newConfigDir, oldConfigDir);
settings.importFinished(newConfigPath);
System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString());
}
@@ -79,38 +84,30 @@ public class ConfigImportHelper {
while (true);
}
@NotNull
private static ConfigImportSettings getConfigImportSettings() {
try {
Class customProviderClass =
Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings");
if (customProviderClass != null) {
if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) {
Constructor constructor = customProviderClass.getDeclaredConstructor();
if (constructor != null) {
return (ConfigImportSettings)constructor.newInstance();
}
}
@SuppressWarnings("unchecked")
Class<ConfigImportSettings> customProviderClass =
(Class<ConfigImportSettings>)Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings");
if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) {
return ReflectionUtil.newInstance(customProviderClass);
}
}
catch (ClassNotFoundException ignored) {
}
catch (NoSuchMethodException ignored) {
}
catch (InvocationTargetException ignored) {
}
catch (InstantiationException ignored) {
}
catch (IllegalAccessException ignored) {
catch (RuntimeException ignored) {
}
return new ConfigImportSettings();
}
@Nullable
private static File findOldConfigDir(String newConfigPath, @Nullable String customPathSelector) {
final File configDir = new File(newConfigPath);
final File selectorDir = CONFIG_RELATED_PATH.length() == 0 ? configDir : configDir.getParentFile();
private static File findOldConfigDir(@NotNull File configDir, @Nullable String customPathSelector) {
final File selectorDir = CONFIG_RELATED_PATH.isEmpty() ? configDir : configDir.getParentFile();
final File parent = selectorDir.getParentFile();
if (parent == null || !parent.exists()) return null;
if (parent == null || !parent.exists()) {
return null;
}
File maxFile = null;
long lastModified = 0;
final String selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName();
@@ -119,14 +116,17 @@ public class ConfigImportHelper {
final String customPrefix = customPathSelector != null ? getPrefixFromSelector(customPathSelector) : null;
for (File file : parent.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
public boolean accept(@NotNull File file, @NotNull String name) {
return StringUtil.startsWithIgnoreCase(name, prefix) ||
customPrefix != null && StringUtil.startsWithIgnoreCase(name, customPrefix);
}
})) {
final File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
if (!options.exists()) continue;
final long modified = options.lastModified();
File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
if (!options.exists()) {
continue;
}
long modified = options.lastModified();
if (modified > lastModified) {
lastModified = modified;
maxFile = file;
@@ -139,9 +139,9 @@ public class ConfigImportHelper {
return (SystemInfo.isMac ? "" : ".") + selector.replaceAll("\\d", "");
}
public static void doImport(final String newConfigPath, final File oldConfigDir) {
private static void doImport(@NotNull File newConfigDir, @NotNull File oldConfigDir) {
try {
xcopy(oldConfigDir, new File(newConfigPath));
copy(oldConfigDir, newConfigDir);
}
catch (IOException e) {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
@@ -150,14 +150,12 @@ public class ConfigImportHelper {
}
}
public static boolean validateOldConfigDir(final File instHome, final File oldConfigDir, ConfigImportSettings settings) {
private static boolean validateOldConfigDir(@Nullable File installationHome, @Nullable File oldConfigDir, @NotNull ConfigImportSettings settings) {
if (oldConfigDir == null) {
final String message = !instHome.equals(oldConfigDir) ?
ApplicationBundle.message("error.invalid.installation.home", instHome.getAbsolutePath(),
settings.getProductName(ThreeState.YES)) :
ApplicationBundle.message("error.invalid.config.folder", instHome.getAbsolutePath(),
settings.getProductName(ThreeState.YES));
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), message);
if (installationHome != null) {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
ApplicationBundle.message("error.invalid.installation.home", installationHome.getAbsolutePath(), settings.getProductName(ThreeState.YES)));
}
return false;
}
@@ -171,7 +169,7 @@ public class ConfigImportHelper {
return true;
}
public static void xcopy(File src, File dest) throws IOException {
private static void copy(@NotNull File src, @NotNull File dest) throws IOException {
src = src.getCanonicalFile();
dest = dest.getCanonicalFile();
if (!src.isDirectory()) {
@@ -184,32 +182,53 @@ public class ConfigImportHelper {
return;
}
FileUtil.copyDir(src, dest);
FileUtil.ensureExists(dest);
// Delete plugins just imported. They're most probably incompatible with newer idea version.
File plugins = new File(dest, PLUGINS_PATH);
File[] childFiles = src.listFiles(new FilenameFilter() {
@Override
public boolean accept(@NotNull File dir, @NotNull String name) {
// Don't copy plugins just imported. They're most probably incompatible with newer idea version.
return !StringUtil.startsWithChar(name, '.') && !name.equals(PLUGINS_PATH);
}
});
if (childFiles == null || childFiles.length == 0) {
return;
}
for (File from : childFiles) {
File to = new File(dest, from.getName());
if (from.isDirectory()) {
FileUtil.copyDir(from, to, false);
}
else {
FileUtil.copy(from, to);
}
}
File plugins = new File(src, PLUGINS_PATH);
if (plugins.exists()) {
final ArrayList<IdeaPluginDescriptorImpl> descriptors = new ArrayList<IdeaPluginDescriptorImpl>();
PluginManager.loadDescriptors(plugins.getPath(), descriptors, null, 0);
final ArrayList<String> oldPlugins = new ArrayList<String>();
List<IdeaPluginDescriptorImpl> descriptors = new SmartList<IdeaPluginDescriptorImpl>();
PluginManagerCore.loadDescriptors(plugins, descriptors, null, 0);
List<String> oldPlugins = new SmartList<String>();
for (IdeaPluginDescriptorImpl descriptor : descriptors) {
oldPlugins.add(descriptor.getPluginId().getIdString());
// check isBundled also - probably plugin is bundled in new IDE version
if (descriptor.isEnabled() && !descriptor.isBundled()) {
oldPlugins.add(descriptor.getPluginId().getIdString());
}
}
if (!oldPlugins.isEmpty()) {
PluginManager.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT));
PluginManagerCore.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT));
}
FileUtil.delete(plugins);
}
File pluginsSettings = new File(new File(dest, "options"), "plugin_ui.xml");
if (pluginsSettings.exists()) {
FileUtil.delete(pluginsSettings);
}
}
@Nullable
public static File getOldConfigDir(File oldInstallHome, ConfigImportSettings settings) {
if (oldInstallHome == null) return null;
public static File getOldConfigDir(@Nullable File oldInstallHome, ConfigImportSettings settings) {
if (oldInstallHome == null) {
return null;
}
// check if it's already config dir
if (new File(oldInstallHome, OPTIONS_XML).exists()) {
return oldInstallHome;
@@ -299,8 +318,8 @@ public class ConfigImportHelper {
@NotNull final String propertyName) {
if (file.getName().endsWith(".properties")) {
try {
InputStream fis = new BufferedInputStream(new FileInputStream(file));
PropertyResourceBundle bundle;
InputStream fis = new BufferedInputStream(new FileInputStream(file));
try {
bundle = new PropertyResourceBundle(fis);
}
@@ -374,7 +393,7 @@ public class ConfigImportHelper {
@Nullable
private static String getContent(File file) {
try {
StringBuffer content = new StringBuffer();
StringBuilder content = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
try {
do {
@@ -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;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -33,19 +33,17 @@ public class Product {
private final Set<String> myCodes;
private final List<UpdateChannel> myChannels;
public Product(Element node) {
public Product(@NotNull Element node) {
myName = node.getAttributeValue("name");
myCodes = new LinkedHashSet<String>();
myChannels = new ArrayList<UpdateChannel>();
List codes = node.getChildren("code");
for (Object code : codes) {
myCodes.add(((Element)code).getValue());
for (Element code : node.getChildren("code")) {
myCodes.add(code.getValue());
}
List channels = node.getChildren("channel");
for (Object channel : channels) {
myChannels.add(new UpdateChannel((Element)channel));
for (Element channel : node.getChildren("channel")) {
myChannels.add(new UpdateChannel(channel));
}
}
@@ -56,7 +54,9 @@ public class Product {
@Nullable
public UpdateChannel findUpdateChannelById(String id) {
for (UpdateChannel channel : myChannels) {
if (id.equals(channel.getId())) return channel;
if (id.equals(channel.getId())) {
return channel;
}
}
return null;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -20,6 +20,7 @@
package com.intellij.openapi.updateSettings.impl;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -39,12 +40,11 @@ public class UpdateChannel {
public static final String LICENSING_EAP = "eap";
public static final String LICENSING_PRODUCTION = "production";
public UpdateChannel(Element node) {
public UpdateChannel(@NotNull Element node) {
myId = node.getAttributeValue("id");
myName = node.getAttributeValue("name");
myStatus = ChannelStatus.fromCode(node.getAttributeValue("status"));
String licensing = node.getAttributeValue("licensing");
myLicensing = licensing != null ? licensing : LICENSING_PRODUCTION;
myLicensing = node.getAttributeValue("licensing", LICENSING_PRODUCTION);
String majorVersion = node.getAttributeValue("majorVersion");
myMajorVersion = majorVersion != null ? Integer.parseInt(majorVersion) : -1;
@@ -56,8 +56,8 @@ public class UpdateChannel {
myFeedbackUrl = node.getAttributeValue("feedback");
myBuilds = new ArrayList<BuildInfo>();
for (Object child : node.getChildren("build")) {
myBuilds.add(new BuildInfo((Element)child));
for (Element child : node.getChildren("build")) {
myBuilds.add(new BuildInfo(child));
}
}
@@ -69,7 +69,6 @@ public class UpdateChannel {
build = info;
}
}
return build;
}
@@ -93,7 +93,7 @@ public final class UpdateChecker {
@NonNls private static final String DISABLED_UPDATE = "disabled_update.txt";
private static Set<String> ourDisabledToUpdatePlugins;
private static Map<String, String> ourAdditionalRequestOptions = new HashMap<String, String>();
private static final Map<String, String> ourAdditionalRequestOptions = new HashMap<String, String>();
private static class Holder {
private static final String UPDATE_URL = ApplicationInfoEx.getInstanceEx().getUpdateUrls().getCheckingUrl();
@@ -464,8 +464,7 @@ public final class UpdateChecker {
private static CheckForUpdateResult checkForUpdates(final UpdateSettings settings) {
UpdatesInfo info;
try {
UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl());
info = loader.loadUpdatesInfo();
info = UpdatesXmlLoader.loadUpdatesInfo(getUpdateUrl());
if (info == null) {
return new CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED);
}
@@ -660,14 +659,12 @@ public final class UpdateChecker {
return uid;
}
}
String uid;
if (!propertiesComponent.isValueSet(INSTALLATION_UID)) {
String uid = propertiesComponent.getValue(INSTALLATION_UID);
if (uid == null) {
uid = generateUUID();
propertiesComponent.setValue(INSTALLATION_UID, uid);
}
else {
uid = propertiesComponent.getValue(INSTALLATION_UID);
}
return uid;
}
@@ -683,11 +680,8 @@ public final class UpdateChecker {
return FileUtil.loadFile(permanentIdFile).trim();
}
String uuid;
if (propertiesComponent.isValueSet(INSTALLATION_UID)) {
uuid = propertiesComponent.getValue(INSTALLATION_UID);
}
else {
String uuid = propertiesComponent.getValue(INSTALLATION_UID);
if (uuid == null) {
uuid = generateUUID();
}
FileUtil.writeToFile(permanentIdFile, uuid);
@@ -764,7 +758,11 @@ public final class UpdateChecker {
String fromBuildNumber = patch.getFromBuild().asStringWithoutProductCode();
String toBuildNumber = newVersion.getNumber().asStringWithoutProductCode();
String bundledJdk = "jdk-bundled".equals(System.getProperty("idea.java.redist")) ? "-jdk-bundled" : "";
String jdkMacRedist = System.getProperty("idea.java.redist");
String bundledJdk = "";
if (jdkMacRedist.lastIndexOf("jdk-bundled") >= 0 ){
bundledJdk = "jdk-bundled".equals(jdkMacRedist) ? "-jdk-bundled" : "-custom-jdk-bundled";
}
String fileName = productCode + "-" + fromBuildNumber + "-" + toBuildNumber + "-patch" + bundledJdk + osSuffix + ".jar";
@@ -812,7 +810,7 @@ public final class UpdateChecker {
out.close();
}
String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase();
String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase(Locale.ENGLISH);
File patchFile = new File(FileUtil.getTempDirectory(), patchFileName);
FileUtil.copy(tempFile, patchFile);
FileUtil.delete(tempFile);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* 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.
@@ -15,7 +15,6 @@
*/
package com.intellij.openapi.updateSettings.impl;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,11 +25,10 @@ import java.util.List;
public class UpdatesInfo {
@NotNull private final List<Product> myProducts;
public UpdatesInfo(Element element) {
public UpdatesInfo(@NotNull Element element) {
myProducts = new ArrayList<Product>();
List children = element.getChildren();
for (Object child : children) {
myProducts.add(new Product((Element) child));
for (Element child : element.getChildren()) {
myProducts.add(new Product(child));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* 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.
@@ -25,33 +25,19 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.net.HttpConfigurable;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class UpdatesXmlLoader {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.updateSettings.impl.UpdatesXmlLoader");
private final String updateUrl;
public UpdatesXmlLoader(final String updatesUrl) {
this.updateUrl = updatesUrl;
}
import java.util.concurrent.*;
class UpdatesXmlLoader {
private static final Logger LOG = Logger.getInstance(UpdatesXmlLoader.class);
@Nullable
public UpdatesInfo loadUpdatesInfo() throws ConnectionException{
LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )");
public static UpdatesInfo loadUpdatesInfo(@Nullable final String updateUrl) throws ConnectionException {
if (LOG.isDebugEnabled()) {
LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )");
}
if (StringUtil.isEmpty(updateUrl)) {
LOG.debug("update url is empty: updates will not be checked");
@@ -59,20 +45,13 @@ public class UpdatesXmlLoader {
}
final Ref<Exception> error = new Ref<Exception>();
FutureTask<UpdatesInfo> ft = new FutureTask<UpdatesInfo>(new Callable<UpdatesInfo>() {
Future<UpdatesInfo> future = ApplicationManager.getApplication().executeOnPooledThread(new Callable<UpdatesInfo>() {
@Nullable
@Override
public UpdatesInfo call() throws Exception {
try {
prepareUrl(updateUrl);
URL requestUrl = prepareRequestUrl(updateUrl);
URLConnection connection = requestUrl.openConnection();
connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
final InputStream inputStream = connection.getInputStream();
Reader reader = new InputStreamReader(inputStream);
String url = updateUrl.startsWith("file:") ? updateUrl : updateUrl + '?' + UpdateChecker.prepareUpdateCheckArgs();
InputStream inputStream = HttpConfigurable.getInstance().openConnection(url).getInputStream();
try {
return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
}
@@ -80,59 +59,41 @@ public class UpdatesXmlLoader {
LOG.info(e); // Broken xml downloaded. Don't bother telling user.
}
finally {
reader.close();
inputStream.close();
}
}
catch (Exception e) {
LOG.debug(e);
error.set(e);
}
return null;
}
});
ApplicationManager.getApplication().executeOnPooledThread(ft);
UpdatesInfo result = null;
try {
UpdatesInfo result = ft.get(5, TimeUnit.SECONDS);
if (!error.isNull()) {
//noinspection ThrowableResultOfMethodCallIgnored
throw new ConnectionException(error.get());
}
return result;
result = future.get(5, TimeUnit.SECONDS);
}
catch (TimeoutException e) {
// ignore
catch (TimeoutException ignored) {
}
catch (Exception e) {
catch (InterruptedException e) {
LOG.debug(e);
throw new ConnectionException(e.getMessage(),e);
error.set(e);
}
if (!ft.isDone()) {
ft.cancel(true);
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
catch (ExecutionException e) {
LOG.debug(e);
error.set(e);
}
return null;
}
protected static void prepareUrl(@NotNull String url) throws ConnectionException {
try {
HttpConfigurable.getInstance().prepareURL(url);
}
catch (Exception e) {
throw new ConnectionException(e);
}
}
protected URL prepareRequestUrl(@NotNull String url) throws ConnectionException {
try {
if (url.startsWith("file:")) {
return new URL(url);
if (!future.isDone()) {
future.cancel(true);
if (error.isNull()) {
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
}
return new URL(url + "?" + UpdateChecker.prepareUpdateCheckArgs());
}
catch (Exception e) {
throw new ConnectionException(e);
if (!error.isNull()) {
throw new ConnectionException(error.get());
}
return result;
}
}
@@ -245,6 +245,7 @@ public class PluginsAdvertiser implements StartupActivity {
final KnownExtensions extensions = loadExtensions();
if (extensions != null && unknownFeatures.isEmpty()) return;
final Runnable runnable = new Runnable() {
@Override
public void run() {
final Application application = ApplicationManager.getApplication();
if (application.isUnitTestMode() || application.isHeadlessEnvironment()) return;
@@ -252,9 +253,10 @@ public class PluginsAdvertiser implements StartupActivity {
private final Set<PluginDownloader> myPlugins = new HashSet<PluginDownloader>();
private List<IdeaPluginDescriptor> myAllPlugins;
private Map<Plugin, IdeaPluginDescriptor> myDisabledPlugins = new HashMap<Plugin, IdeaPluginDescriptor>();
private final Map<Plugin, IdeaPluginDescriptor> myDisabledPlugins = new HashMap<Plugin, IdeaPluginDescriptor>();
private List<String> myBundledPlugin;
@Override
public void run() {
try {
myAllPlugins = RepositoryHelper.loadPluginsFromRepository(null);
@@ -349,6 +351,7 @@ public class PluginsAdvertiser implements StartupActivity {
@MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false)
public Map<String, PluginSet> myExtensions = new HashMap<String, PluginSet>();
@SuppressWarnings("unused")
public KnownExtensions() {
}
@@ -371,6 +374,7 @@ public class PluginsAdvertiser implements StartupActivity {
public static class PluginSet {
public Set<Plugin> myPlugins = new HashSet<Plugin>();
@SuppressWarnings("unused")
public PluginSet() {
}
@@ -28,7 +28,6 @@ import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.DimensionService;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.WelcomeScreen;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.components.labels.LinkLabel;
@@ -150,7 +149,7 @@ public class NewWelcomeScreen extends JPanel implements WelcomeScreen {
}
public static boolean isNewWelcomeScreen(@NotNull AnActionEvent e) {
return e.getPlace() == ActionPlaces.WELCOME_SCREEN && Registry.is("ide.new.welcome.screen");
return e.getPlace() == ActionPlaces.WELCOME_SCREEN && FlatWelcomeFrameProvider.isAvailable();
}
private static class WelcomeScreenGroup extends DefaultActionGroup {
@@ -1,5 +1,4 @@
error.invalid.installation.home=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} installation home.
error.invalid.config.folder=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} config folder.
error.no.settings.path=Unable to import settings. {0} does not exist.
title.settings.import.failed=Settings Import Failed
error.unable.to.import.settings=Unable to import settings. {0}
@@ -116,8 +116,8 @@
<lang.syntaxHighlighterFactory key="XHTML" implementationClass="com.intellij.lang.xhtml.XhtmlSyntaxHighlighterFactory"/>
<lang.syntaxHighlighterFactory key="DTD" implementationClass="com.intellij.lang.dtd.DtdSyntaxHighlighterFactory"/>
<annotator language="XML" implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlNamespaceAnnotator"/>
<annotator language="XML" implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlNsPrefixAnnotator"/>
<annotator language="XML" implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlNamespaceAnnotator"/>
<renameHandler id="xmlTagRenameHandler" implementation="com.intellij.xml.refactoring.XmlTagRenameHandler"/>
<renameHandler implementation="com.intellij.xml.refactoring.SchemaPrefixRenameHandler" order="before xmlTagRenameHandler"/>
@@ -583,8 +583,8 @@
<group id="ChangeScheme">
<action id="ChangeColorScheme" class="com.intellij.ide.actions.QuickChangeColorSchemeAction"/>
<action id="ChangeKeymap" class="com.intellij.ide.actions.QuickChangeKeymapAction"/>
<action id="ChangeLaf" class="com.intellij.ide.actions.QuickChangeLookAndFeel"/>
<action id="ChangeView" class="com.intellij.ide.actions.QuickChangeViewModeAction"/>
<action id="ChangeLaf" class="com.intellij.ide.actions.QuickChangeLookAndFeel"/>
</group>
<action id="MaintenanceAction" class="com.intellij.ide.actions.MaintenanceAction"/>
@@ -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,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() {
}
@@ -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,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();
}
@@ -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 {
}
@@ -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) {
@@ -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);
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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());
}
}
@@ -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();
}
}
}
@@ -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();
}
}
@@ -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();
}
@@ -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);
}
@@ -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();
}
@@ -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);
}
@@ -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);
}
@@ -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();
}
}
@@ -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();
}
}
@@ -51,7 +51,7 @@ ide.debugger.inline.dark.fg.color=61,128,101
ide.debugger.inline.dark.fg.color.description=Inline values foreground for dark editor scheme
ide.debugger.inline.fg.modified.color=202,128,33
ide.debugger.inline.fg.modified.color.description=Inline modified values foreground
ide.debugger.inline.dark.fg.modified.color=161,131,10
ide.debugger.inline.dark.fg.modified.color=202,126,3
ide.debugger.inline.dark.fg.modified.color.description=Inline modified values foreground for dark editor scheme
ide.debugMode.description=Record additional information to make bug reports more informative.
@@ -198,6 +198,9 @@ compiler.process.use.memory.temp.cache=true
compiler.process.use.memory.temp.cache.description=Store temporary data in memory for faster compilation;\
requires larger heap size for the build process. If parallel build is enabled, the option is ignored and temp data is always stored in memory.
compiler.process.preload=false
compiler.process.preload.description=After build finishes, the IDE will pre-load and leave waiting in memory the build process for the next compilation. This will save time for process start and project model loading (may be noticeable for big projects).\
compiler.process.debug.port=-1
compiler.automake.trigger.delay=300
@@ -26,7 +26,10 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.JBColor;
import com.intellij.ui.SimpleColoredText;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.NotNullProducer;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XSourcePosition;
@@ -95,7 +98,7 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
catch (Exception e) {
continue;
}
final Color color = bpLine == lineNumber ? new JBColor(Gray._180, new Color(147, 217, 186)) : getForeground();
final Color color = bpLine == lineNumber ? new JBColor(new Color(0, 255, 86), new Color(255, 235, 9)) : getForeground();
final String name = value.getName();
if (StringUtil.isEmpty(text.toString())) {
@@ -89,6 +89,10 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
protected abstract Project getProject();
private static void setInplaceEditorBounds(JComponent component, int x, int y, int width, int height) {
component.setBounds(x, y, width, Math.max(height, component.getPreferredSize().height));
}
public final void show() {
LOG.assertTrue(myInplaceEditorComponent == null, "editor is not released");
final JTree tree = getTree();
@@ -108,12 +112,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
final JComponent inplaceEditorComponent = createInplaceEditorComponent();
myInplaceEditorComponent = inplaceEditorComponent;
LOG.assertTrue(inplaceEditorComponent != null);
inplaceEditorComponent.setBounds(
layeredPanePoint.x,
layeredPanePoint.y,
bounds.width,
Math.max(bounds.height, inplaceEditorComponent.getPreferredSize().height)
);
setInplaceEditorBounds(inplaceEditorComponent, layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height);
layeredPane.add(inplaceEditorComponent, new Integer(250));
@@ -145,7 +144,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
return;
}
Point layeredPanePoint = SwingUtilities.convertPoint(tree, bounds.x, bounds.y, layeredPane);
inplaceEditorComponent.setBounds(layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height);
setInplaceEditorBounds(inplaceEditorComponent, layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height);
inplaceEditorComponent.revalidate();
}
});
@@ -160,10 +160,11 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
};
if (getValueContainer().computeInlineDebuggerData(callback) == ThreeState.UNSURE) {
getValueContainer().computeSourcePosition(new XNearestSourcePosition() {
class ValueDeclaration implements XNavigatable {
@Override
public void setSourcePosition(@Nullable XSourcePosition sourcePosition) {
final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map =
myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
final Map<VirtualFile, Long> timestamps = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS);
if (map == null || timestamps == null || sourcePosition == null) return;
VirtualFile file = sourcePosition.getFile();
@@ -172,7 +173,10 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
int line = sourcePosition.getLine();
callback.computed(file, doc, line);
}
});
}
class NearestValuePosition extends ValueDeclaration implements XNearestSourcePosition {}
getValueContainer().computeSourcePosition(new ValueDeclaration());
getValueContainer().computeSourcePosition(new NearestValuePosition());
}
}
}
@@ -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;
}
}
@@ -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());
}
}
@@ -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());
}
}
@@ -55,5 +55,10 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unnecessary unboxing</problem_class>
<description>Unnecessary unboxing &lt;code&gt;b.byteValue()&lt;/code&gt; #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 &lt;code&gt;((Double) o).doubleValue()&lt;/code&gt; #loc</description>
</problem>
</problems>
@@ -35,7 +35,7 @@ import java.util.List;
public class HgUpdateEnvironment implements UpdateEnvironment {
private final Project project;
private final HgUpdateConfigurationSettings updateConfiguration;
@NotNull private final HgUpdateConfigurationSettings updateConfiguration;
public HgUpdateEnvironment(Project project) {
this.project = project;
@@ -89,7 +89,7 @@ public class HgUpdateEnvironment implements UpdateEnvironment {
private final HgUpdateConfigurationSettings updateConfiguration;
protected HgUpdateDialog updateDialog;
public UpdateConfigurable(HgUpdateConfigurationSettings updateConfiguration) {
public UpdateConfigurable(@NotNull HgUpdateConfigurationSettings updateConfiguration) {
this.updateConfiguration = updateConfiguration;
}
@@ -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()));
@@ -40,15 +40,15 @@ public class TasksIcons {
public static final Icon Github = load("/icons/github.png"); // 16x16
public static final Icon Gitlab = load("/icons/gitlab.png"); // 16x16
public static final Icon Jira = load("/icons/jira.png"); // 16x16
public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16
public static final Icon Lighthouse = load("/icons/lighthouse.png"); // 16x16
public static final Icon Mantis = load("/icons/mantis.png"); // 16x16
public static final Icon Other = load("/icons/other.png"); // 16x16
public static class Pivotal {
public static final Icon Bug = load("/icons/pivotal/bug.png"); // 14x14
public static final Icon Chore = load("/icons/pivotal/chore.png"); // 14x14
public static final Icon Feature = load("/icons/pivotal/feature.png"); // 14x14
public static final Icon Release = load("/icons/pivotal/release.png"); // 14x14
public static final Icon Bug = load("/icons/pivotal/bug.png"); // 16x16
public static final Icon Chore = load("/icons/pivotal/chore.png"); // 16x16
public static final Icon Feature = load("/icons/pivotal/feature.png"); // 16x16
public static final Icon Release = load("/icons/pivotal/release.png"); // 16x16
}
public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16
Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 325 B

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