From d4a6ae921e38a73143530dc8798bf649fbd538b6 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 4 Dec 2014 21:43:36 +0300 Subject: [PATCH 001/231] Initial version of custom task states for JIRA >= 5.0 --- .../com/intellij/tasks/CustomTaskState.java | 14 ++++ .../com/intellij/tasks/TaskRepository.java | 26 ++++++- .../intellij/tasks/TaskRepositoryType.java | 4 +- .../src/com/intellij/tasks/TaskState.java | 33 +++++++-- .../intellij/tasks/jira/JiraRemoteApi.java | 9 ++- .../intellij/tasks/jira/JiraRepository.java | 17 ++--- .../intellij/tasks/jira/rest/JiraRestApi.java | 11 ++- .../tasks/jira/rest/api2/JiraRestApi2.java | 38 +++++++---- .../rest/api2/model/JiraCustomTaskState.java | 39 +++++++++++ .../api2/model/JiraTransitionsWrapper.java | 57 ++++++++++++++++ .../rest/api20alpha1/JiraRestApi20Alpha1.java | 35 +++++----- .../tasks/jira/soap/JiraLegacyApi.java | 12 +++- .../tasks/actions/OpenTaskDialog.form | 18 +++-- .../tasks/actions/OpenTaskDialog.java | 67 +++++++++++++++---- .../com/intellij/tasks/impl/TaskUiUtil.java | 13 ++-- 15 files changed, 311 insertions(+), 82 deletions(-) create mode 100644 plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java create mode 100644 plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java create mode 100644 plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java new file mode 100644 index 000000000000..2f8cf8de2c64 --- /dev/null +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java @@ -0,0 +1,14 @@ +package com.intellij.tasks; + +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public interface CustomTaskState { + @NotNull + String getId(); + + @NotNull + String getPresentableName(); +} diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 416a7158eb26..0d971ab18b80 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.Set; import java.util.concurrent.Callable; /** @@ -164,6 +165,17 @@ public abstract class TaskRepository { return getIssues(query, offset, limit, withClosed); } + /** + * Retrieve states available for task from server. One of these states will be passed later to {@link #setTaskState(Task, TaskState)}. + * @param task task to update + * @return set of available states + */ + @NotNull + public Set getPossibleStates(@NotNull Task task) throws Exception { + //noinspection unchecked + return getRepositoryType().getPossibleTaskStates(); + } + /** * @param id task ID. Don't forget to define {@link #extractId(String)}, if your server uses not PROJECT-123 format for task IDs. * @return found task or {@code null} otherwise. Basically you should return {@code null} on e.g. 404 error and throw exception with @@ -179,6 +191,15 @@ public abstract class TaskRepository { @Nullable public abstract String extractId(@NotNull String taskName); + + /** + * @deprecated Use {@link #setTaskState(Task, CustomTaskState)} instead + */ + @Deprecated + public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + throw new UnsupportedOperationException("Setting task to state " + state + " is not supported"); + } + /** * Update state of the task on server. Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and * supported states in {@link TaskRepositoryType#getPossibleTaskStates()}. @@ -188,10 +209,11 @@ public abstract class TaskRepository { * @see com.intellij.tasks.TaskRepositoryType#getPossibleTaskStates() * @see com.intellij.tasks.TaskRepository#getFeatures() */ - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { - throw new UnsupportedOperationException("Setting task to state " + state + " is not supported"); + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { + setTaskState(task, ((TaskState)state)); } + // for serialization public TaskRepository() { myType = null; diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java index f348f4264c22..fac6ad863524 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java @@ -67,8 +67,10 @@ public abstract class TaskRepositoryType implements Ta public abstract Class getRepositoryClass(); /** - * @return states that can be set by {@link TaskRepository#setTaskState(Task, TaskState)} + * @return states that can be set by {@link TaskRepository#setTaskState(Task, CustomTaskState)} + * @deprecated Use {@link com.intellij.tasks.TaskRepository#getPossibleStates(Task)} instead. */ + @Deprecated public EnumSet getPossibleTaskStates() { return EnumSet.noneOf(TaskState.class); } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java index c0c0a2628b9d..27b8fb87c473 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java @@ -15,16 +15,35 @@ */ package com.intellij.tasks; +import org.jetbrains.annotations.NotNull; + /** * @author Dmitry Avdeev */ -public enum TaskState { +public enum TaskState implements CustomTaskState { + SUBMITTED("Submitted"), + OPEN("Open"), + IN_PROGRESS("In Progress"), + REOPENED("Reopened"), + RESOLVED("Resolved"), - SUBMITTED, - OPEN, - IN_PROGRESS, - REOPENED, - RESOLVED, + OTHER("Other"); - OTHER + String myPresentableName; + + TaskState(@NotNull String presentableName) { + myPresentableName = presentableName; + } + + @NotNull + @Override + public String getId() { + return ""; + } + + @NotNull + @Override + public String getPresentableName() { + return myPresentableName; + } } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java index 8ee9c97512a1..11efe39cc3de 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java @@ -1,8 +1,8 @@ package com.intellij.tasks.jira; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; -import com.intellij.tasks.TaskState; import com.intellij.tasks.jira.rest.api2.JiraRestApi2; import com.intellij.tasks.jira.rest.api20alpha1.JiraRestApi20Alpha1; import com.intellij.tasks.jira.soap.JiraLegacyApi; @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Set; /** * Because of the number of available remote interfaces in JIRA, {@link JiraRepository} delegates @@ -29,7 +30,10 @@ public abstract class JiraRemoteApi { @Nullable public abstract Task findTask(@NotNull String key) throws Exception; - public abstract void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception; + @NotNull + public abstract Set getPossibleStates(@NotNull Task task) throws Exception; + + public abstract void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception; public abstract void updateTimeSpend(@NotNull LocalTask task, @NotNull String timeSpent, String comment) throws Exception; @@ -80,6 +84,5 @@ public abstract class JiraRemoteApi { public String getVersionName() { return myVersionName; } - } } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java index 820bb22426e0..cea2c21a4e75 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java @@ -22,10 +22,10 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskState; import com.intellij.tasks.impl.BaseRepositoryImpl; import com.intellij.tasks.impl.gson.GsonUtil; import com.intellij.tasks.jira.rest.JiraRestApi; @@ -44,10 +44,7 @@ import org.jetbrains.annotations.Nullable; import java.io.InputStream; import java.net.URL; -import java.util.Collections; -import java.util.Hashtable; -import java.util.List; -import java.util.Vector; +import java.util.*; import java.util.regex.Pattern; /** @@ -352,10 +349,16 @@ public class JiraRepository extends BaseRepositoryImpl { } @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { myApiVersion.setTaskState(task, state); } + @NotNull + @Override + public Set getPossibleStates(@NotNull Task task) throws Exception { + return myApiVersion.getPossibleStates(task); + } + public void setSearchQuery(String searchQuery) { mySearchQuery = searchQuery; } @@ -371,8 +374,6 @@ public class JiraRepository extends BaseRepositoryImpl { /** * Used to preserve discovered API version for the next initialization. - * - * @return */ @SuppressWarnings("UnusedDeclaration") @Nullable diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java index 502eed083e74..447a5c58adbe 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java @@ -2,8 +2,8 @@ package com.intellij.tasks.jira.rest; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.Task; -import com.intellij.tasks.TaskState; import com.intellij.tasks.jira.JiraRemoteApi; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.JiraVersion; @@ -99,19 +99,16 @@ public abstract class JiraRestApi extends JiraRemoteApi { protected abstract JiraIssue parseIssue(String response); @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { String requestBody = getRequestForStateTransition(state); LOG.debug(String.format("Transition: %s -> %s, request: %s", task.getState(), state, requestBody)); - if (requestBody == null) { - return; - } PostMethod method = new PostMethod(myRepository.getRestUrl("issue", task.getId(), "transitions")); method.setRequestEntity(createJsonEntity(requestBody)); myRepository.executeMethod(method); } - @Nullable - protected abstract String getRequestForStateTransition(@NotNull TaskState state); + @NotNull + protected abstract String getRequestForStateTransition(@NotNull CustomTaskState state); protected static RequestEntity createJsonEntity(String requestBody) { try { diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java index 0c9b647ee720..3ec3b99d3e6a 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java @@ -3,11 +3,14 @@ package com.intellij.tasks.jira.rest.api2; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; -import com.intellij.tasks.TaskState; +import com.intellij.tasks.Task; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; +import com.intellij.tasks.jira.rest.api2.model.JiraCustomTaskState; import com.intellij.tasks.jira.rest.api2.model.JiraIssueApi2; +import com.intellij.tasks.jira.rest.api2.model.JiraTransitionsWrapper; import com.intellij.tasks.jira.rest.model.JiraIssue; import com.intellij.tasks.jira.rest.model.JiraResponseWrapper; import org.apache.commons.httpclient.methods.GetMethod; @@ -18,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * This REST API version is used in JIRA 5.1.8 and above (including JIRA 6.x.x). @@ -63,21 +67,27 @@ public class JiraRestApi2 extends JiraRestApi { return JiraRepository.GSON.fromJson(response, JiraIssueApi2.class); } - @Nullable + @NotNull @Override - protected String getRequestForStateTransition(@NotNull TaskState state) { - // REST API 2.0 require double quotes both around field names and values (even numbers) - switch (state) { - case IN_PROGRESS: - return "{\"transition\": {\"id\": \"4\"}}"; - case RESOLVED: - // 5 for "Resolved", 2 for "Closed" - return "{\"transition\": {\"id\": \"5\"}, \"fields\": {\"resolution\": {\"name\": \"Fixed\"}}}"; - case REOPENED: - return "{\"transition\": {\"id\": \"3\"}}"; - default: - return null; + protected String getRequestForStateTransition(@NotNull CustomTaskState state) { + final JiraCustomTaskState transition = (JiraCustomTaskState)state; + assert StringUtil.isNotEmpty(state.getId()); + if (transition.hasResolutionId()) { + return "{\"transition\": {\"id\": \"" + state.getId() + "\"}, \"fields\": {\"resolution\": {\"id\": \"" + transition.getResolutionId() + "\"}}}"; } + else { + return "{\"transition\": {\"id\": \"" + state.getId() + "\"}}"; + } + } + + @NotNull + @Override + public Set getPossibleStates(@NotNull Task task) throws Exception { + final GetMethod method = new GetMethod(myRepository.getRestUrl("issue", task.getId(), "transitions")); + method.setQueryString("expand=transitions.fields"); + final String response = myRepository.executeMethod(method); + final JiraTransitionsWrapper wrapper = JiraRepository.GSON.fromJson(response, JiraTransitionsWrapper.class); + return wrapper.getTransitions(); } @Override diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java new file mode 100644 index 000000000000..81520d82f6b4 --- /dev/null +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java @@ -0,0 +1,39 @@ +package com.intellij.tasks.jira.rest.api2.model; + +import com.intellij.tasks.CustomTaskState; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JiraCustomTaskState implements CustomTaskState { + private final int myTransitionId; + private final String myPresentableName; + private final int myResolutionId; + + public JiraCustomTaskState(int transitionId, @NotNull String presentableName, int resolutionId) { + myTransitionId = transitionId; + myPresentableName = presentableName; + myResolutionId = resolutionId; + } + + public boolean hasResolutionId() { + return myResolutionId != 0; + } + + public int getResolutionId() { + return myResolutionId; + } + + @NotNull + @Override + public String getId() { + return String.valueOf(myTransitionId); + } + + @NotNull + @Override + public String getPresentableName() { + return myPresentableName; + } +} diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java new file mode 100644 index 000000000000..1768307c0d09 --- /dev/null +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java @@ -0,0 +1,57 @@ +package com.intellij.tasks.jira.rest.api2.model; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import com.intellij.tasks.CustomTaskState; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +/** + * @author Mikhail Golubev + */ +public class JiraTransitionsWrapper { + private List transitions = Collections.emptyList(); + + static class JiraTransition { + private int id; + private String name; + @SerializedName("to") + private JiraTaskState target; + private JsonObject fields; + + static class JiraTaskState { + private int id; + private String name; + } + } + + @NotNull + public Set getTransitions() { + final Set result = new LinkedHashSet(); + for (JiraTransition transition : transitions) { + final int transitionId = transition.id; + final String transitionName = transition.target.name; + String fieldName = null; + if (transition.fields != null) { + for (Map.Entry field : transition.fields.entrySet()) { + fieldName = field.getKey(); + final JsonObject fieldInfo = field.getValue().getAsJsonObject(); + if (fieldName.equals("resolution") && fieldInfo.get("required").getAsBoolean()) { + for (JsonElement allowedValue : fieldInfo.getAsJsonArray("allowedValues")) { + final String resolutionName = allowedValue.getAsJsonObject().get("name").getAsString(); + final int resolutionId = allowedValue.getAsJsonObject().get("id").getAsInt(); + result.add(new JiraCustomTaskState(transitionId, transitionName + " (" + resolutionName + ")", resolutionId)); + } + break; + } + } + } + if (fieldName == null) { + result.add(new JiraCustomTaskState(transitionId, transitionName, 0)); + } + } + return result; + } +} diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java index 7de17945ac31..6ccfc6b1f526 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java @@ -2,9 +2,11 @@ package com.intellij.tasks.jira.rest.api20alpha1; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; +import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskState; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; import com.intellij.tasks.jira.rest.JiraRestTask; @@ -12,24 +14,33 @@ import com.intellij.tasks.jira.rest.api20alpha1.model.JiraIssueApi20Alpha1; import com.intellij.tasks.jira.rest.model.JiraIssue; import com.intellij.tasks.jira.rest.model.JiraResponseWrapper; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; /** * This REST API is used in JIRA versions from 4.2 to 4.4. + * * @author Mikhail Golubev */ public class JiraRestApi20Alpha1 extends JiraRestApi { private static final Logger LOG = Logger.getInstance(JiraRestApi20Alpha1.class); - private static final Type ISSUES_WRAPPER_TYPE = new TypeToken>() { /* empty */ }.getType(); + private static final Type ISSUES_WRAPPER_TYPE = new TypeToken>() { /* empty */ + }.getType(); public JiraRestApi20Alpha1(JiraRepository repository) { super(repository); } + @NotNull + @Override + public Set getPossibleStates(@NotNull Task task) throws Exception { + return Collections.emptySet(); + } + @Override protected JiraIssue parseIssue(String response) { return JiraRepository.GSON.fromJson(response, JiraIssueApi20Alpha1.class); @@ -55,20 +66,12 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { return updatedIssues; } - @Nullable + @NotNull @Override - protected String getRequestForStateTransition(@NotNull TaskState state) { - switch (state) { - case IN_PROGRESS: - return "{\"transition\": \"4\"}"; - case RESOLVED: - // 5 for "Resolved", 2 for "Closed" - return "{\"transition\": \"5\", \"resolution\": \"Fixed\"}"; - case REOPENED: - return "{\"transition\": \"3\"}"; - default: - return null; - } + protected String getRequestForStateTransition(@NotNull CustomTaskState state) { + final String stateId = state.getId(); + assert StringUtil.isNotEmpty(stateId); + return "{\"transition\": \"" + stateId + "\"}"; } @Override diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java index e8cbee842cda..857c6e11aa5e 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java @@ -1,10 +1,10 @@ package com.intellij.tasks.jira.soap; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskState; import com.intellij.tasks.impl.TaskUtil; import com.intellij.tasks.jira.JiraRemoteApi; import com.intellij.tasks.jira.JiraRepository; @@ -19,7 +19,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.List; +import java.util.Set; /** * Legacy integration restored due to IDEA-120595. @@ -102,8 +104,14 @@ public class JiraLegacyApi extends JiraRemoteApi { return ApiType.LEGACY; } + @NotNull @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { + public Set getPossibleStates(@NotNull Task task) throws Exception { + return Collections.emptySet(); + } + + @Override + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { throw new Exception(TaskBundle.message("jira.failure.no.state.update")); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index fb7ab62bdaa8..69fcfb993d05 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -8,7 +8,7 @@ - + @@ -18,7 +18,7 @@ - + @@ -31,13 +31,19 @@ - + - + + + + + + + - - + + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 2cc241e4d8a1..b1008d493f63 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -20,6 +20,7 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.binding.BindControl; import com.intellij.openapi.options.binding.ControlBinder; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; @@ -30,8 +31,10 @@ import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.VcsTaskHandler; import com.intellij.tasks.*; import com.intellij.tasks.impl.TaskManagerImpl; +import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater; import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.util.containers.ContainerUtil; @@ -42,6 +45,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Set; /** * @author Dmitry Avdeev @@ -50,10 +54,23 @@ public class OpenTaskDialog extends DialogWrapper { private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.actions.SimpleOpenTaskDialog"); public static final String START_FROM_BRANCH = "start.from.branch"; + private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState() { + @NotNull + @Override + public String getId() { + return ""; + } + + @NotNull + @Override + public String getPresentableName() { + return "-- do not update --"; + } + }; + private JPanel myPanel; @BindControl(value = "clearContext", instant = true) private JCheckBox myClearContext; - private JCheckBox myMarkAsInProgressBox; private JLabel myTaskNameLabel; private JPanel myVcsPanel; private JTextField myBranchName; @@ -62,6 +79,7 @@ public class OpenTaskDialog extends DialogWrapper { private JBCheckBox myCreateChangelist; private JBLabel myFromLabel; private ComboBox myBranchFrom; + private ComboBox myStateComboBox; private final Project myProject; private final Task myTask; @@ -81,10 +99,35 @@ public class OpenTaskDialog extends DialogWrapper { binder.bindAnnotations(this); binder.reset(); - TaskRepository repository = task.getRepository(); - myMarkAsInProgressBox.setSelected(manager.getState().markAsInProgress); - if (!TaskUtil.isStateSupported(repository, TaskState.IN_PROGRESS)) { - myMarkAsInProgressBox.setVisible(false); + myStateComboBox.setRenderer(new ListCellRendererWrapper() { + @Override + public void customize(JList list, CustomTaskState value, int index, boolean selected, boolean hasFocus) { + if (value != null) { + setText(value.getPresentableName()); + } + else { + setText("-- no states available --"); + } + } + }); + + // Capture correct modality state + final TaskRepository repository = myTask.getRepository(); + if (repository != null) { + // Find out proper way to determine modality state here + new ComboBoxUpdater(myProject, "Fetching available task states...", myStateComboBox) { + @NotNull + @Override + protected Set fetch(@NotNull ProgressIndicator indicator) throws Exception { + return repository.getPossibleStates(myTask); + } + + @Nullable + @Override + public CustomTaskState getExtraItem() { + return DO_NOT_UPDATE_STATE; + } + }.queue(); } TaskManagerImpl.Config state = taskManager.getState(); @@ -186,14 +229,14 @@ public class OpenTaskDialog extends DialogWrapper { public void createTask() { final TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject); - taskManager.getState().markAsInProgress = isMarkAsInProgress(); taskManager.getState().createChangelist = myCreateChangelist.isSelected(); taskManager.getState().createBranch = myCreateBranch.isSelected(); TaskRepository repository = myTask.getRepository(); - if (isMarkAsInProgress() && repository != null) { + final CustomTaskState selectedItem = (CustomTaskState)myStateComboBox.getSelectedItem(); + if (repository != null && selectedItem != null && selectedItem != DO_NOT_UPDATE_STATE) { try { - repository.setTaskState(myTask, TaskState.IN_PROGRESS); + repository.setTaskState(myTask, selectedItem); } catch (Exception ex) { Messages.showErrorDialog(myProject, ex.getMessage(), "Cannot Set State For Issue"); @@ -252,10 +295,6 @@ public class OpenTaskDialog extends DialogWrapper { return myClearContext.isSelected(); } - private boolean isMarkAsInProgress() { - return myMarkAsInProgressBox.isSelected() && myMarkAsInProgressBox.isVisible(); - } - @NonNls protected String getDimensionServiceKey() { return "SimpleOpenTaskDialog"; @@ -277,4 +316,8 @@ public class OpenTaskDialog extends DialogWrapper { protected JComponent createCenterPanel() { return myPanel; } + + private void createUIComponents() { + myStateComboBox = new ComboBox(300); + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java index 9f28f8868ae7..b130f375cfb8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java @@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.List; +import java.util.Collection; /** * @author Mikhail Golubev @@ -33,13 +33,18 @@ public class TaskUiUtil { public abstract static class RemoteFetchTask extends Task.Backgroundable { protected T myResult; protected Exception myException; - private final ModalityState myModalityState = ModalityState.current(); + private final ModalityState myModalityState; /** * Should be called only from EDT, so current modality state can be captured. */ protected RemoteFetchTask(@Nullable Project project, @NotNull String title) { + this(project, title, ModalityState.current()); + } + + protected RemoteFetchTask(@Nullable Project project, @NotNull String title, @NotNull ModalityState modalityState) { super(project, title); + myModalityState = modalityState; } @Override @@ -80,11 +85,11 @@ public class TaskUiUtil { * Auxiliary remote fetcher designed to simplify updating of combo boxes in repository editors, which is * indeed a rather common task. */ - public static abstract class ComboBoxUpdater extends RemoteFetchTask> { + public static abstract class ComboBoxUpdater extends RemoteFetchTask> { protected final ComboBox myComboBox; public ComboBoxUpdater(@Nullable Project project, @NotNull String title, @NotNull ComboBox comboBox) { - super(project, title); + super(project, title, ModalityState.any()); myComboBox = comboBox; } From 8d9456bcddd62ebc5ae62f77d855b1d33f2fd212 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 5 Dec 2014 18:00:04 +0300 Subject: [PATCH 002/231] Restore possibility to set one of the standard states for issues in JIRA 4.x --- .../com/intellij/tasks/TaskRepository.java | 8 +++-- .../intellij/tasks/jira/rest/JiraRestApi.java | 2 +- .../tasks/jira/rest/api2/JiraRestApi2.java | 11 ++++--- ...r.java => JiraTransitionsWrapperApi2.java} | 8 ++--- .../rest/api20alpha1/JiraRestApi20Alpha1.java | 33 ++++++++++++------- .../{api2 => }/model/JiraCustomTaskState.java | 16 ++++----- 6 files changed, 45 insertions(+), 33 deletions(-) rename plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/{JiraTransitionsWrapper.java => JiraTransitionsWrapperApi2.java} (83%) rename plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/{api2 => }/model/JiraCustomTaskState.java (63%) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 0d971ab18b80..535ba131f985 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -193,7 +193,7 @@ public abstract class TaskRepository { /** - * @deprecated Use {@link #setTaskState(Task, CustomTaskState)} instead + * @deprecated Use {@link #setTaskState(Task, CustomTaskState)} instead. */ @Deprecated public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { @@ -201,8 +201,10 @@ public abstract class TaskRepository { } /** - * Update state of the task on server. Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and - * supported states in {@link TaskRepositoryType#getPossibleTaskStates()}. + * Update state of the task on server. It's guaranteed that only issues returned by {@link #getPossibleStates(Task)} + * will be passed here. + *

+ * Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and supported states in {@link #getPossibleStates(Task)}. * * @param task issue to update * @param state new state of the issue diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java index 447a5c58adbe..78919e390d5f 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/JiraRestApi.java @@ -107,7 +107,7 @@ public abstract class JiraRestApi extends JiraRemoteApi { myRepository.executeMethod(method); } - @NotNull + @Nullable protected abstract String getRequestForStateTransition(@NotNull CustomTaskState state); protected static RequestEntity createJsonEntity(String requestBody) { diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java index 3ec3b99d3e6a..72cdc8130960 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java @@ -8,9 +8,9 @@ import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; -import com.intellij.tasks.jira.rest.api2.model.JiraCustomTaskState; import com.intellij.tasks.jira.rest.api2.model.JiraIssueApi2; -import com.intellij.tasks.jira.rest.api2.model.JiraTransitionsWrapper; +import com.intellij.tasks.jira.rest.api2.model.JiraTransitionsWrapperApi2; +import com.intellij.tasks.jira.rest.model.JiraCustomTaskState; import com.intellij.tasks.jira.rest.model.JiraIssue; import com.intellij.tasks.jira.rest.model.JiraResponseWrapper; import org.apache.commons.httpclient.methods.GetMethod; @@ -72,8 +72,9 @@ public class JiraRestApi2 extends JiraRestApi { protected String getRequestForStateTransition(@NotNull CustomTaskState state) { final JiraCustomTaskState transition = (JiraCustomTaskState)state; assert StringUtil.isNotEmpty(state.getId()); - if (transition.hasResolutionId()) { - return "{\"transition\": {\"id\": \"" + state.getId() + "\"}, \"fields\": {\"resolution\": {\"id\": \"" + transition.getResolutionId() + "\"}}}"; + final String resolutionName = transition.getResolutionName(); + if (resolutionName != null) { + return "{\"transition\": {\"id\": \"" + state.getId() + "\"}, \"fields\": {\"resolution\": {\"name\": \"" + resolutionName + "\"}}}"; } else { return "{\"transition\": {\"id\": \"" + state.getId() + "\"}}"; @@ -86,7 +87,7 @@ public class JiraRestApi2 extends JiraRestApi { final GetMethod method = new GetMethod(myRepository.getRestUrl("issue", task.getId(), "transitions")); method.setQueryString("expand=transitions.fields"); final String response = myRepository.executeMethod(method); - final JiraTransitionsWrapper wrapper = JiraRepository.GSON.fromJson(response, JiraTransitionsWrapper.class); + final JiraTransitionsWrapperApi2 wrapper = JiraRepository.GSON.fromJson(response, JiraTransitionsWrapperApi2.class); return wrapper.getTransitions(); } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java similarity index 83% rename from plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java rename to plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java index 1768307c0d09..3c1df68b4d35 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapper.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java @@ -4,6 +4,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; import com.intellij.tasks.CustomTaskState; +import com.intellij.tasks.jira.rest.model.JiraCustomTaskState; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -11,7 +12,7 @@ import java.util.*; /** * @author Mikhail Golubev */ -public class JiraTransitionsWrapper { +public class JiraTransitionsWrapperApi2 { private List transitions = Collections.emptyList(); static class JiraTransition { @@ -41,15 +42,14 @@ public class JiraTransitionsWrapper { if (fieldName.equals("resolution") && fieldInfo.get("required").getAsBoolean()) { for (JsonElement allowedValue : fieldInfo.getAsJsonArray("allowedValues")) { final String resolutionName = allowedValue.getAsJsonObject().get("name").getAsString(); - final int resolutionId = allowedValue.getAsJsonObject().get("id").getAsInt(); - result.add(new JiraCustomTaskState(transitionId, transitionName + " (" + resolutionName + ")", resolutionId)); + result.add(new JiraCustomTaskState(transitionName + " (" + resolutionName + ")", transitionId, resolutionName)); } break; } } } if (fieldName == null) { - result.add(new JiraCustomTaskState(transitionId, transitionName, 0)); + result.add(new JiraCustomTaskState(transitionName, transitionId, null)); } } return result; diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java index 6ccfc6b1f526..a87f6052d93b 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java @@ -2,11 +2,7 @@ package com.intellij.tasks.jira.rest.api20alpha1; import com.google.gson.reflect.TypeToken; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.tasks.CustomTaskState; -import com.intellij.tasks.LocalTask; -import com.intellij.tasks.Task; -import com.intellij.tasks.TaskBundle; +import com.intellij.tasks.*; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; import com.intellij.tasks.jira.rest.JiraRestTask; @@ -14,10 +10,11 @@ import com.intellij.tasks.jira.rest.api20alpha1.model.JiraIssueApi20Alpha1; import com.intellij.tasks.jira.rest.model.JiraIssue; import com.intellij.tasks.jira.rest.model.JiraResponseWrapper; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -38,7 +35,11 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { @NotNull @Override public Set getPossibleStates(@NotNull Task task) throws Exception { - return Collections.emptySet(); + final HashSet result = new HashSet(); + result.add(TaskState.IN_PROGRESS); + result.add(TaskState.RESOLVED); + result.add(TaskState.REOPENED); + return result; } @Override @@ -66,12 +67,22 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { return updatedIssues; } - @NotNull + @Nullable @Override protected String getRequestForStateTransition(@NotNull CustomTaskState state) { - final String stateId = state.getId(); - assert StringUtil.isNotEmpty(stateId); - return "{\"transition\": \"" + stateId + "\"}"; + // REST API of JIRA 4.x for retrieving possible transitions is very limited: we can't fetch possible resolutions and + // names of transition destinations. So we have no other options than to hardcode them. + switch ((TaskState)state) { + case IN_PROGRESS: + return "{\"transition\": \"4\"}"; + case RESOLVED: + // 5 for "Resolved", 2 for "Closed" + return "{\"transition\": \"5\", \"resolution\": \"Fixed\"}"; + case REOPENED: + return "{\"transition\": \"3\"}"; + default: + return null; + } } @Override diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java similarity index 63% rename from plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java rename to plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java index 81520d82f6b4..96fafeb5fa66 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraCustomTaskState.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java @@ -1,7 +1,8 @@ -package com.intellij.tasks.jira.rest.api2.model; +package com.intellij.tasks.jira.rest.model; import com.intellij.tasks.CustomTaskState; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Mikhail Golubev @@ -9,19 +10,16 @@ import org.jetbrains.annotations.NotNull; public class JiraCustomTaskState implements CustomTaskState { private final int myTransitionId; private final String myPresentableName; - private final int myResolutionId; + private final String myResolutionId; - public JiraCustomTaskState(int transitionId, @NotNull String presentableName, int resolutionId) { + public JiraCustomTaskState(@NotNull String presentableName, int transitionId, @Nullable String resolutionName) { myTransitionId = transitionId; myPresentableName = presentableName; - myResolutionId = resolutionId; + myResolutionId = resolutionName; } - public boolean hasResolutionId() { - return myResolutionId != 0; - } - - public int getResolutionId() { + @Nullable + public String getResolutionName() { return myResolutionId; } From f5024828297bacbacb559f92849220ace1149313 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 22 Dec 2014 22:31:30 +0200 Subject: [PATCH 003/231] do not show dialog when reformat code is invoked on file in editor --- .../actions/ReformatCodeAction.java | 41 +++++-------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index bcbd0fd6738d..e040f24d482e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -30,6 +30,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ShowSettingsUtil; @@ -138,12 +139,9 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); - boolean processWholeFile = false; boolean processChangedTextOnly = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file); - final boolean showDialog = EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG; - if (file == null && dir != null) { DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir); if (options != null) { @@ -151,36 +149,17 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } return; } - else if (showDialog) { - LayoutCodeOptions selectedFlags = getLayoutCodeOptions(project, file, dir, hasSelection); - if (selectedFlags == null) - return; - optimizeImports = selectedFlags.isOptimizeImports(); - rearrangeEntries = selectedFlags.isRearrangeEntries(); - processWholeFile = selectedFlags.isProcessWholeFile(); - processChangedTextOnly = selectedFlags.isProcessOnlyChangedText(); + if (file == null || editor == null) return; - if (selectedFlags.isProcessDirectory()) { - assert dir != null : "File = " + file + ", Element = " + CommonDataKeys.PSI_ELEMENT.getData(dataContext); - reformatDirectory(project, dir, selectedFlags); - return; - } - } - - if (file == null) return; - - if (!showDialog && processChangedTextOnly && isChangeNotTrackedForFile(project, file)) { + TextRange range = null; + if (hasSelection) { processChangedTextOnly = false; + SelectionModel model = editor.getSelectionModel(); + range = TextRange.create(model.getSelectionStart(), model.getSelectionEnd()); } - - final TextRange range; - final boolean processSelectedText = !processWholeFile && hasSelection; - if (processSelectedText) { - range = TextRange.create(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd()); - } - else{ - range = null; + else if (processChangedTextOnly && isChangeNotTrackedForFile(project, file)) { + processChangedTextOnly = false; } AbstractLayoutCodeProcessor processor; @@ -189,10 +168,10 @@ public class ReformatCodeAction extends AnAction implements DumbAware { processor = new ReformatCodeProcessor(processor, processChangedTextOnly); } else { - processor = new ReformatCodeProcessor(project, file, range, !processSelectedText && processChangedTextOnly); + processor = new ReformatCodeProcessor(project, file, range, processChangedTextOnly); } - if (rearrangeEntries && editor != null) { + if (rearrangeEntries) { processor = new RearrangeCodeProcessor(processor); } From 580faba56dfde69d56bc282b7d470a76cebc9ba0 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 23 Dec 2014 00:08:43 +0200 Subject: [PATCH 004/231] Refactored LayoutCodeDialog, now it is invoked by default on "Ctrl-Shift-Alt-L", corrected all usages --- .../AbstractLayoutCodeProcessorTest.java | 36 +- .../actions/AbstractLayoutCodeProcessor.java | 6 +- .../actions/FormatChangedTextUtil.java | 6 +- .../codeInsight/actions/LayoutCodeDialog.form | 135 +++++++ .../codeInsight/actions/LayoutCodeDialog.java | 381 +++++------------- .../actions/LayoutCodeOptions.java | 12 +- .../actions/LayoutProjectCodeDialog.java | 14 +- .../actions/OptimizeImportsAction.java | 61 +-- .../actions/OptimizeImportsProcessor.java | 4 + .../actions/OptionalReformatActions.java | 24 ++ .../actions/ReformatCodeAction.java | 174 +++++--- .../actions/ReformatFileAction.java | 81 ++++ .../actions/ReformatFilesDialog.java | 12 +- .../actions/ReformatFilesOptions.java | 8 +- .../src/idea/Keymap_Default.xml | 3 + .../src/idea/LangActions.xml | 2 + 16 files changed, 546 insertions(+), 413 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java index fbd85a3b62a5..f1cab2fe1188 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java @@ -317,7 +317,7 @@ class AdditionalEventInfo { } } -class MockReformatFileSettings implements LayoutCodeOptions { +class MockReformatFileSettings implements ReformatFilesOptions { private boolean myProcessWholeFile; private boolean myProcessDirectories; private boolean myRearrange; @@ -325,6 +325,7 @@ class MockReformatFileSettings implements LayoutCodeOptions { private boolean myOptimizeImports; private boolean myProcessOnlyChangedText; private boolean myIsOK = true; + private TextRangeType myTextRangeType; @Nullable @Override @@ -338,34 +339,28 @@ class MockReformatFileSettings implements LayoutCodeOptions { return null; } - @Override - public boolean isProcessWholeFile() { - return myProcessWholeFile; - } - MockReformatFileSettings setProcessWholeFile(boolean processWholeFile) { myProcessWholeFile = processWholeFile; return this; } - @Override - public boolean isProcessDirectory() { - return myProcessDirectories; - } - MockReformatFileSettings setProcessDirectory(boolean processDirectories) { myProcessDirectories = processDirectories; return this; } @Override - public boolean isRearrangeEntries() { - return myRearrange; + public TextRangeType getTextRangeType() { + return null; + } + + public void setTextRangeType(TextRangeType textRangeType) { + myTextRangeType = textRangeType; } @Override - public boolean isIncludeSubdirectories() { - return myIncludeSubdirs; + public boolean isRearrangeCode() { + return myRearrange; } @Override @@ -379,17 +374,6 @@ class MockReformatFileSettings implements LayoutCodeOptions { return this; } - @Override - public boolean isProcessOnlyChangedText() { - return myProcessOnlyChangedText; - } - - @NotNull - MockReformatFileSettings setProcessOnlyChangedText(boolean processOnlyChangedText) { - myProcessOnlyChangedText = processOnlyChangedText; - return this; - } - @NotNull MockReformatFileSettings setRearrange(boolean rearrange) { myRearrange = rearrange; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 5fd44fe874ac..3b4ed45f3c35 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -67,7 +67,7 @@ public abstract class AbstractLayoutCodeProcessor { private final String myProgressText; private final String myCommandName; - private final Runnable myPostRunnable; + private Runnable myPostRunnable; private boolean myProcessChangedTextOnly; protected AbstractLayoutCodeProcessor myPreviousCodeProcessor; @@ -169,6 +169,10 @@ public abstract class AbstractLayoutCodeProcessor { return list; } + public void setPostRunnable(Runnable postRunnable) { + myPostRunnable = postRunnable; + } + @Nullable private FutureTask getPreviousProcessorTask(@NotNull PsiFile file, boolean processChangedTextOnly) { return myPreviousCodeProcessor != null ? myPreviousCodeProcessor.preprocessFile(file, processChangedTextOnly) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 45effe8e781e..aca2397c531f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -297,9 +297,9 @@ public class FormatChangedTextUtil { } @NotNull - private static List calculateChangedTextRanges(@NotNull Project project, - @NotNull PsiFile file, - @NotNull String contentFromVcs) throws FilesTooBigForDiffException + protected static List calculateChangedTextRanges(@NotNull Project project, + @NotNull PsiFile file, + @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException { Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false); Document document = PsiDocumentManager.getInstance(project).getDocument(file); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form new file mode 100644 index 000000000000..b6e07f4c8a5b --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form @@ -0,0 +1,135 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 716d2f884844..177461c4cf6a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -16,279 +16,160 @@ package com.intellij.codeInsight.actions; -import com.intellij.CommonBundle; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageImportStatements; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.arrangement.Rearranger; -import com.intellij.psi.search.SearchScope; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; + +import static com.intellij.codeInsight.actions.ReformatCodeAction.getLastSavedRearrangeCbState; public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions { @NotNull private final Project myProject; - @Nullable private final PsiFile myFile; - @Nullable private final PsiDirectory myDirectory; - private final Boolean myTextSelected; + @NotNull private final PsiFile myFile; - private JRadioButton myRbFile; - private JRadioButton myRbSelectedText; - private JRadioButton myRbDirectory; - private JCheckBox myCbIncludeSubdirs; - private JCheckBox myCbOptimizeImports; - private JCheckBox myCbArrangeEntries; - private JCheckBox myCbOnlyVcsChangedRegions; - private JCheckBox myDoNotAskMeCheckBox; + private final boolean myTextSelected; private final String myHelpId; - @Nullable private CommonCodeStyleSettings myCommonSettings; - private boolean myRearrangeAlwaysEnabled; - private final boolean myOptimizeImportProcessorsForFileLanguageExists; - private final boolean myRearrangerProcessorsForFileLanguageExists; - private final boolean myFileHasChanges; + private boolean myLastRunOptimizeImportsWasEnabled; + private boolean myLastRunOnlyVcsChangedTextEnabled; + private boolean myLastRunRearrangeWasEnabled; - private boolean myOptimizeImportsSelected; - private boolean myFormatOnlyVCSChangedRegionsSelected; - private boolean myDoNotShowDialogSelected; - private boolean myRearrangeEntriesSelected; + private JPanel myButtonsPanel; + private JCheckBox myOptimizeImportsCb; + private JCheckBox myRearrangeCodeCb; - public LayoutCodeDialog(@NotNull Project project, - @NotNull String title, - @Nullable PsiFile file, - @Nullable PsiDirectory directory, - Boolean isTextSelected, + private JRadioButton myOnlyVCSChangedTextRb; + private JRadioButton mySelectedTextRadioButton; + private JRadioButton myWholeFileRadioButton; + + private JPanel myActionsPanel; + private JPanel myScopePanel; + + public LayoutCodeDialog(@NotNull Project project, + @NotNull PsiFile file, + boolean textSelected, final String helpId) { super(project, true); myFile = file; myProject = project; - myDirectory = directory; - myTextSelected = isTextSelected; + myTextSelected = textSelected; + myHelpId = helpId; - myOptimizeImportProcessorsForFileLanguageExists = myFile != null && !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty(); - myRearrangerProcessorsForFileLanguageExists = myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; - myFileHasChanges = myFile != null && FormatChangedTextUtil.hasChanges(myFile); - - if (myFile != null) myCommonSettings = CodeStyleSettingsManager.getSettings(myProject).getCommonSettings(myFile.getLanguage()); - myRearrangeAlwaysEnabled = myCommonSettings != null - && myCommonSettings.isForceArrangeMenuAvailable() - && myCommonSettings.FORCE_REARRANGE_MODE == CommonCodeStyleSettings.REARRANGE_ALWAYS; + myLastRunOptimizeImportsWasEnabled = ReformatFilesDialog.isOptmizeImportsOptionOn(); + myLastRunRearrangeWasEnabled = getLastSavedRearrangeCbState(project, file); + myLastRunOnlyVcsChangedTextEnabled = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); - setTitle(title); + setTitle("Reformat File: " + file.getName()); + init(); - myHelpId = helpId; } - @Override protected void init() { super.init(); - loadCbsStates(); - setUpInitialSelection(); - - myRbFile.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveEnabledCbsSelectedState(); - setUpCbsStateForFileFormatting(); - } - }); - - myRbDirectory.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveEnabledCbsSelectedState(); - setUpCbsStatesForDirectoryFormatting(); - } - }); - - myRbSelectedText.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - saveEnabledCbsSelectedState(); - setUpCbsStatesForSelectedTextFormatting(); - } - }); + setUpActions(); + setUpTextRangeMode(); } - private void setUpInitialSelection() { - if (myTextSelected == Boolean.TRUE) { - myRbSelectedText.setSelected(true); - setUpCbsStatesForSelectedTextFormatting(); + @Override + public TextRangeType getTextRangeType() { + if (myOnlyVCSChangedTextRb.isSelected()) { + return TextRangeType.VCS_CHANGED_TEXT; + } + if (mySelectedTextRadioButton.isSelected()) { + return TextRangeType.SELECTED_TEXT; + } + return TextRangeType.WHOLE_FILE; + } + + private void setUpTextRangeMode() { + mySelectedTextRadioButton.setEnabled(myTextSelected); + if (!myTextSelected) { + mySelectedTextRadioButton.setToolTipText("No text selected in editor"); + } + + final boolean fileHasChanges = FormatChangedTextUtil.hasChanges(myFile); + if (myFile.getVirtualFile() instanceof LightVirtualFile) { + myOnlyVCSChangedTextRb.setVisible(false); } else { - if (myFile != null) { - myRbFile.setSelected(true); - setUpCbsStateForFileFormatting(); - } - else { - myRbDirectory.setSelected(true); - setUpCbsStatesForDirectoryFormatting(); + myOnlyVCSChangedTextRb.setEnabled(fileHasChanges); + if (!fileHasChanges) { + String hint = getChangesNotAvailableHint(); + if (hint != null) myOnlyVCSChangedTextRb.setToolTipText(hint); } } - myCbIncludeSubdirs.setSelected(true); - } - private void loadCbsStates() { - myOptimizeImportsSelected = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false); - myRearrangeEntriesSelected = myRearrangeAlwaysEnabled || ReformatCodeAction.getLastSavedRearrangeCbState(myProject, myFile); - myFormatOnlyVCSChangedRegionsSelected = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); - } + myWholeFileRadioButton.setEnabled(true); - private void saveEnabledCbsSelectedState() { - if (myCbArrangeEntries.isEnabled()) { - myRearrangeEntriesSelected = myCbArrangeEntries.isSelected(); + if (myTextSelected) { + mySelectedTextRadioButton.setSelected(true); } - if (myCbOptimizeImports.isEnabled()) { - myOptimizeImportsSelected = myCbOptimizeImports.isSelected(); + else if (myLastRunOnlyVcsChangedTextEnabled && fileHasChanges) { + myOnlyVCSChangedTextRb.setSelected(true); } - if (myCbOnlyVcsChangedRegions.isEnabled()) { - myFormatOnlyVCSChangedRegionsSelected = myCbOnlyVcsChangedRegions.isSelected(); - } - if (myDoNotAskMeCheckBox.isEnabled()) { - myDoNotShowDialogSelected = myDoNotAskMeCheckBox.isSelected(); + else { + myWholeFileRadioButton.setSelected(true); } } - private void setUpCbsStateForFileFormatting() { - myCbOptimizeImports.setEnabled(myOptimizeImportProcessorsForFileLanguageExists); - myCbOptimizeImports.setSelected(myOptimizeImportProcessorsForFileLanguageExists && myOptimizeImportsSelected); + private void setUpActions() { + boolean canOptimizeImports = !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty(); + myOptimizeImportsCb.setVisible(canOptimizeImports); + if (canOptimizeImports) { + myOptimizeImportsCb.setSelected(myLastRunOptimizeImportsWasEnabled); + } - myCbArrangeEntries.setEnabled(myRearrangerProcessorsForFileLanguageExists); - myCbArrangeEntries.setSelected(myRearrangerProcessorsForFileLanguageExists && myRearrangeEntriesSelected); - - myCbOnlyVcsChangedRegions.setEnabled(myFileHasChanges); - myCbOnlyVcsChangedRegions.setSelected(myFileHasChanges && myFormatOnlyVCSChangedRegionsSelected); - - myDoNotAskMeCheckBox.setEnabled(true); - myDoNotAskMeCheckBox.setSelected(myDoNotShowDialogSelected); - - myCbIncludeSubdirs.setEnabled(false); + boolean canRearrangeCode = Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; + myRearrangeCodeCb.setVisible(canRearrangeCode); + if (canRearrangeCode) { + myRearrangeCodeCb.setSelected(myLastRunRearrangeWasEnabled); + } } - private void setUpCbsStatesForDirectoryFormatting() { - myCbOptimizeImports.setEnabled(true); - myCbOptimizeImports.setSelected(myOptimizeImportsSelected); - - myCbArrangeEntries.setEnabled(true); - myCbArrangeEntries.setSelected(myRearrangeEntriesSelected); - - myCbOnlyVcsChangedRegions.setEnabled(myDirectory != null && FormatChangedTextUtil.hasChanges(myDirectory)); - myCbOnlyVcsChangedRegions.setSelected(false); - - myDoNotAskMeCheckBox.setEnabled(false); - myDoNotAskMeCheckBox.setSelected(false); - - myCbIncludeSubdirs.setEnabled(true); + @Nullable + private String getChangesNotAvailableHint() { + if (!VcsUtil.isFileUnderVcs(myProject, VcsUtil.getFilePath(myFile.getVirtualFile()))) { + return "File not under VCS root"; + } + else if (!FormatChangedTextUtil.hasChanges(myFile)) { + return "File was not changed since last revision"; + } + return null; } - private void setUpCbsStatesForSelectedTextFormatting() { - myCbOptimizeImports.setEnabled(false); - myCbOptimizeImports.setSelected(false); + private void saveCurrentConfiguration() { + if (myOptimizeImportsCb.isEnabled()) { + String optimizeImports = Boolean.toString(isOptimizeImports()); + PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, optimizeImports); + } + if (myRearrangeCodeCb.isEnabled()) { + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, myFile.getLanguage(), isRearrangeCode()); + } - myCbArrangeEntries.setEnabled(true); - myCbArrangeEntries.setSelected(myRearrangeEntriesSelected); - - myCbOnlyVcsChangedRegions.setEnabled(false); - myCbOnlyVcsChangedRegions.setSelected(false); - - myDoNotAskMeCheckBox.setEnabled(true); - myDoNotAskMeCheckBox.setSelected(myDoNotShowDialogSelected); - - myCbIncludeSubdirs.setEnabled(false); + if (!mySelectedTextRadioButton.isSelected()) { + String formatVcsChangedRegions = Boolean.toString(myOnlyVCSChangedTextRb.isSelected()); + PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, formatVcsChangedRegions); + } } + @Nullable @Override protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new GridBagLayout()); - panel.setBorder(BorderFactory.createEmptyBorder(4, 8, 8, 0)); - GridBagConstraints gbConstraints = new GridBagConstraints(); - gbConstraints.gridy = 0; - gbConstraints.gridx = 0; - gbConstraints.gridwidth = 3; - gbConstraints.gridheight = 1; - gbConstraints.weightx = 1; - - gbConstraints.fill = GridBagConstraints.BOTH; - gbConstraints.insets = new Insets(0, 0, 0, 0); - - myRbFile = new JRadioButton(CodeInsightBundle.message("process.scope.file", - (myFile != null ? "'" + myFile.getVirtualFile().getPresentableUrl() + "'" : ""))); - panel.add(myRbFile, gbConstraints); - - myRbSelectedText = new JRadioButton(CodeInsightBundle.message("reformat.option.selected.text")); - if (myTextSelected != null) { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myRbSelectedText, gbConstraints); - } - - myRbDirectory = new JRadioButton(); - myCbIncludeSubdirs = new JCheckBox(CodeInsightBundle.message("reformat.option.include.subdirectories")); - if (myDirectory != null) { - myRbDirectory.setText(CodeInsightBundle.message("reformat.option.all.files.in.directory", - myDirectory.getVirtualFile().getPresentableUrl())); - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myRbDirectory, gbConstraints); - - if (myDirectory.getSubdirectories().length > 0) { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 20, 0, 0); - panel.add(myCbIncludeSubdirs, gbConstraints); - } - } - - myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports")); - if (myTextSelected != null && LanguageImportStatements.INSTANCE.hasAnyExtensions()) { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myCbOptimizeImports, gbConstraints); - } - - myCbArrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries")); - if (myDirectory != null || myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null) - { - gbConstraints.gridy++; - gbConstraints.insets = new Insets(0, 0, 0, 0); - panel.add(myCbArrangeEntries, gbConstraints); - } - - myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region")); - gbConstraints.gridy++; - panel.add(myCbOnlyVcsChangedRegions, gbConstraints); - - ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(myRbFile); - buttonGroup.add(myRbSelectedText); - buttonGroup.add(myRbDirectory); - - myRbFile.setEnabled(myFile != null); - myRbSelectedText.setEnabled(myTextSelected == Boolean.TRUE); - - return panel; - } - - @Override - protected JComponent createSouthPanel() { - JComponent southPanel = super.createSouthPanel(); - myDoNotAskMeCheckBox = new JCheckBox(CommonBundle.message("dialog.options.do.not.show")); - return DialogWrapper.addDoNotShowCheckBox(southPanel, myDoNotAskMeCheckBox); + return myButtonsPanel; } @NotNull @@ -303,80 +184,18 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions } @Override - public boolean isProcessWholeFile() { - return myRbFile.isSelected(); - } - - @Override - public boolean isProcessDirectory() { - return myRbDirectory.isSelected(); - } - - @Override - public boolean isIncludeSubdirectories() { - return myCbIncludeSubdirs.isSelected(); + public boolean isRearrangeCode() { + return myRearrangeCodeCb.isEnabled() && myRearrangeCodeCb.isSelected(); } @Override public boolean isOptimizeImports() { - return myCbOptimizeImports.isSelected(); - } - - @Override - public boolean isRearrangeEntries() { - return myCbArrangeEntries.isSelected(); - } - - @Nullable - @Override - public String getFileTypeMask() { - return null; - } - - @Nullable - @Override - public SearchScope getSearchScope() { - return null; - } - - @Override - public boolean isProcessOnlyChangedText() { - return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected(); - } - - public boolean isDoNotAskMe() { - if (myDoNotAskMeCheckBox.isEnabled()) { - return myDoNotAskMeCheckBox.isSelected(); - } - else { - return !EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG; - } + return myOptimizeImportsCb.isEnabled() && myOptimizeImportsCb.isSelected(); } @Override protected void doOKAction() { super.doOKAction(); - persistEnabledCbsStates(); - } - - private void persistEnabledCbsStates() { - if (myCbOptimizeImports.isEnabled()) { - String optimizeImports = Boolean.toString(myCbOptimizeImports.isSelected()); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, optimizeImports); - } - if (myCbOnlyVcsChangedRegions.isEnabled()) { - String formatVcsChangedRegions = Boolean.toString(myCbOnlyVcsChangedRegions.isSelected()); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, formatVcsChangedRegions); - } - if (myCbArrangeEntries.isEnabled()) { - saveRearrangeCbState(myCbArrangeEntries.isSelected()); - } - } - - private void saveRearrangeCbState(boolean isSelected) { - if (myFile != null) - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, myFile.getLanguage(), isSelected); - else - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isSelected); + saveCurrentConfiguration(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java index 5a05a9ac13ab..2400e3b628af 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java @@ -15,10 +15,14 @@ */ package com.intellij.codeInsight.actions; -public interface LayoutCodeOptions extends DirectoryFormattingOptions { +public interface LayoutCodeOptions extends OptionalReformatActions { - boolean isProcessWholeFile(); - - boolean isProcessDirectory(); + TextRangeType getTextRangeType(); } + +enum TextRangeType { + VCS_CHANGED_TEXT, + SELECTED_TEXT, + WHOLE_FILE +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java index 7f76f1b012a5..f6964417ac56 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java @@ -177,7 +177,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi } @Override - public boolean isRearrangeEntries() { + public boolean isRearrangeCode() { return myCbRearrangeEntries.isSelected(); } @@ -190,7 +190,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi protected void doOKAction() { super.doOKAction(); PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports())); - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeCode()); if (myEnableOnlyVCSChangedTextCb) { PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected())); } @@ -200,10 +200,6 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi return myCbOptimizeImports.isSelected(); } - public boolean isProcessOnlyChangedText() { - return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected(); - } - @Nullable public String getFileTypeMask() { if (myEnableFileNameFilterCb.isSelected()) { @@ -232,4 +228,10 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi return false; } + @Override + public TextRangeType getTextRangeType() { + return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected() + ? TextRangeType.VCS_CHANGED_TEXT + : TextRangeType.WHOLE_FILE; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java index bc18a4241360..5eb588e6d5fd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java @@ -17,11 +17,11 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageImportStatements; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -72,13 +72,16 @@ public class OptimizeImportsAction extends AnAction { if (projectContext != null || moduleContext != null) { final String text; + final boolean hasChanges; if (moduleContext != null) { text = CodeInsightBundle.message("process.scope.module", moduleContext.getName()); + hasChanges = FormatChangedTextUtil.hasChanges(moduleContext); } else { text = CodeInsightBundle.message("process.scope.project", projectContext.getPresentableUrl()); + hasChanges = FormatChangedTextUtil.hasChanges(projectContext); } - DialogWrapper dialog = new OptimizeOnModuleDialog(project, text); + DialogWrapper dialog = new OptimizeImportsDialog(project, text, hasChanges); if (!dialog.showAndGet()) { return; } @@ -106,29 +109,21 @@ public class OptimizeImportsAction extends AnAction { } } - boolean processDirectory; - boolean includeSubdirectories; - - if (ApplicationManager.getApplication().isUnitTestMode()) { - includeSubdirectories = processDirectory = false; - } - else if (!EditorSettingsExternalizable.getInstance().getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG && file != null) { - includeSubdirectories = processDirectory = false; - } - else { - final LayoutCodeDialog dialog = - new LayoutCodeDialog(project, CodeInsightBundle.message("process.optimize.imports"), file, dir, null, HELP_ID); - if (!dialog.showAndGet()) { + boolean processDirectory = false; + boolean processOnlyVcsChangedFiles = false; + if (!ApplicationManager.getApplication().isUnitTestMode() && file == null && dir != null) { + String message = CodeInsightBundle.message("process.scope.directory", dir.getName()); + OptimizeImportsDialog dialog = new OptimizeImportsDialog(project, message, FormatChangedTextUtil.hasChanges(dir)); + dialog.show(); + if (!dialog.isOK()) { return; } - EditorSettingsExternalizable.getInstance().getOptions().SHOW_OPIMIZE_IMPORTS_DIALOG = !dialog.isDoNotAskMe(); - ReformatCodeAction.updateShowDialogSetting(dialog, "\"Optimize Imports\" dialog disabled"); - processDirectory = dialog.isProcessDirectory(); - includeSubdirectories = dialog.isIncludeSubdirectories(); + processDirectory = true; + processOnlyVcsChangedFiles = dialog.isProcessOnlyVcsChangedFiles(); } if (processDirectory){ - new OptimizeImportsProcessor(project, dir, includeSubdirectories).run(); + new OptimizeImportsProcessor(project, dir, true, processOnlyVcsChangedFiles).run(); } else{ new OptimizeImportsProcessor(project, file).run(); @@ -204,21 +199,41 @@ public class OptimizeImportsAction extends AnAction { return !LanguageImportStatements.INSTANCE.forFile(file).isEmpty(); } - private static class OptimizeOnModuleDialog extends DialogWrapper { + private static class OptimizeImportsDialog extends DialogWrapper { private final String myText; + private final boolean myContextHasChanges; + private JCheckBox myOnlyVcsCheckBox; - OptimizeOnModuleDialog(Project project, String text) { + OptimizeImportsDialog(Project project, String text, boolean hasChanges) { super(project, false); myText = text; + myContextHasChanges = hasChanges; setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(CodeInsightBundle.message("process.optimize.imports")); init(); } + public boolean isProcessOnlyVcsChangedFiles() { + return myOnlyVcsCheckBox.isSelected(); + } + @Nullable @Override protected JComponent createCenterPanel() { - return new JLabel(myText); + JPanel panel = new JPanel(); + BoxLayout layout = new BoxLayout(panel, BoxLayout.Y_AXIS); + panel.setLayout(layout); + + panel.add(new JLabel(myText)); + myOnlyVcsCheckBox = new JCheckBox("only VCS changed files"); + + boolean lastRunVcsChangedTextEnabled = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); + + myOnlyVcsCheckBox.setEnabled(myContextHasChanges); + myOnlyVcsCheckBox.setSelected(myContextHasChanges && lastRunVcsChangedTextEnabled); + + panel.add(myOnlyVcsCheckBox); + return panel; } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index 6cdb063c0434..b693fb782ad7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -48,6 +48,10 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, false); } + public OptimizeImportsProcessor(Project project, PsiDirectory directory, boolean includeSubdirs, boolean processOnlyVcsChangedFiles) { + super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processOnlyVcsChangedFiles); + } + public OptimizeImportsProcessor(Project project, PsiFile file) { super(project, file, PROGRESS_TEXT, COMMAND_NAME, false); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java new file mode 100644 index 000000000000..e71f5c116ad5 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptionalReformatActions.java @@ -0,0 +1,24 @@ +/* + * 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.codeInsight.actions; + +public interface OptionalReformatActions { + + boolean isOptimizeImports(); + + boolean isRearrangeCode(); + +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index e040f24d482e..348de0668dbc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -16,24 +16,22 @@ package com.intellij.codeInsight.actions; -import com.intellij.application.options.editor.EditorOptions; import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.hint.HintManagerImpl; +import com.intellij.codeInsight.hint.HintUtil; import com.intellij.find.impl.FindInProjectUtil; import com.intellij.formatting.FormattingModelBuilder; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageFormatting; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationListener; -import com.intellij.notification.NotificationType; -import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.module.Module; -import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; @@ -41,13 +39,13 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.ui.LightweightHint; +import com.intellij.util.diff.FilesTooBigForDiffException; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -55,7 +53,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import javax.swing.*; -import javax.swing.event.HyperlinkEvent; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -96,14 +93,14 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (selectedFlags == null) return; - final boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText(); + final boolean processOnlyChangedText = selectedFlags.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; final boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb(); AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null, processOnlyChangedText); if (shouldOptimizeImports) { processor = new OptimizeImportsProcessor(processor); } - if (selectedFlags.isRearrangeEntries()) { + if (selectedFlags.isRearrangeCode()) { processor = new RearrangeCodeProcessor(processor); } @@ -138,9 +135,9 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } } - boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); + final boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); boolean processChangedTextOnly = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); - boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file); + final boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file); if (file == null && dir != null) { DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir); @@ -153,13 +150,23 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (file == null || editor == null) return; TextRange range = null; + TextRangeType textRangeType; if (hasSelection) { processChangedTextOnly = false; + textRangeType = TextRangeType.SELECTED_TEXT; SelectionModel model = editor.getSelectionModel(); range = TextRange.create(model.getSelectionStart(), model.getSelectionEnd()); } - else if (processChangedTextOnly && isChangeNotTrackedForFile(project, file)) { - processChangedTextOnly = false; + else if (processChangedTextOnly) { + textRangeType = TextRangeType.VCS_CHANGED_TEXT; + + if (isChangeNotTrackedForFile(project, file)) { + textRangeType = TextRangeType.WHOLE_FILE; + processChangedTextOnly = false; + } + } + else { + textRangeType = TextRangeType.WHOLE_FILE; } AbstractLayoutCodeProcessor processor; @@ -175,9 +182,98 @@ public class ReformatCodeAction extends AnAction implements DumbAware { processor = new RearrangeCodeProcessor(processor); } + final Document document = PsiDocumentManager.getInstance(project).getDocument(file); + final CharSequence charSeqBefore = document != null ? document.getImmutableCharSequence() : null; + + final PsiFile finalFile = file; + final TextRangeType finalTextRangeType = textRangeType; + + //todo show it if available options =) + + processor.setPostRunnable(new Runnable() { + @Override + public void run() { + if (document != null) { + int totalLinesProcessed = getProcessedLinesNumber(finalFile, charSeqBefore); + String info = prepareMessage(totalLinesProcessed, optimizeImports, rearrangeEntries, finalTextRangeType); + showHint(editor, info); + } + } + }); + processor.run(); } + + private void showHint(@NotNull Editor editor, @NotNull String info) { + JComponent component = HintUtil.createInformationLabel(info); + LightweightHint hint = new LightweightHint(component); + HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, + HintManager.HIDE_BY_ANY_KEY| + HintManager.HIDE_BY_TEXT_CHANGE| + HintManager.HIDE_BY_SCROLLING, + 0, false); + } + + @NotNull + private String prepareMessage(int totalLinesProcessed, boolean optimizeImports, boolean rearrangeCode, @NotNull TextRangeType textRangeType) { + String linesInfo = ""; + if (totalLinesProcessed == 0) { + linesInfo = "No changes needed"; + } + else if (totalLinesProcessed > 0) { + linesInfo = "Changed " + totalLinesProcessed + " lines"; + } + + String scopeInfo = textRangeType == TextRangeType.VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null; + String actionsInfo = "Performed: formatting"; + if (optimizeImports) { + actionsInfo += ", import optimization"; + } + if (rearrangeCode) { + actionsInfo += " and code rearrangement"; + } + + String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText( + ActionManager.getInstance().getAction("ReformatFile")); + + String info = linesInfo; + if (scopeInfo != null) { + info += scopeInfo; + } + info += "\n"; + info += actionsInfo + "\n"; + info += shortcutInfo; + + return info; + } + + + private int getProcessedLinesNumber(final PsiFile file, final CharSequence before) { + Project project = file.getProject(); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + if (document == null) { + return 0; + } + + int totalLinesProcessed = 0; + try { + List ranges = FormatChangedTextUtil.calculateChangedTextRanges(project, file, before); + for (TextRange range : ranges) { + int lineStartNumber = document.getLineNumber(range.getStartOffset()); + int lineEndNumber = document.getLineNumber(range.getEndOffset()); + + int linesCoveredByRange = lineEndNumber - lineStartNumber + 1; + totalLinesProcessed += linesCoveredByRange; + } + } + catch (FilesTooBigForDiffException e) { + e.printStackTrace(); + } + return totalLinesProcessed; + } + + private static boolean isChangeNotTrackedForFile(@NotNull Project project, @NotNull PsiFile file) { boolean isUnderVcs = VcsUtil.isFileUnderVcs(project, VcsUtil.getFilePath(file.getVirtualFile())); if (!isUnderVcs) return true; @@ -215,10 +311,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { @NotNull DirectoryFormattingOptions options) { AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor( - project, - dir, - options.isIncludeSubdirectories(), - options.isProcessOnlyChangedText() + project, dir, options.isIncludeSubdirectories(), options.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT ); registerScopeFilter(processor, options.getSearchScope()); @@ -227,7 +320,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { if (options.isOptimizeImports()) { processor = new OptimizeImportsProcessor(processor); } - if (options.isRearrangeEntries()) { + if (options.isRearrangeCode()) { processor = new RearrangeCodeProcessor(processor); } @@ -239,7 +332,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { @NotNull ReformatFilesOptions selectedFlags) { boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb(); - boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText(); + boolean processOnlyChangedText = selectedFlags.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; AbstractLayoutCodeProcessor processor; if (moduleContext != null) @@ -254,7 +347,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { processor = new OptimizeImportsProcessor(processor); } - if (selectedFlags.isRearrangeEntries()) { + if (selectedFlags.isRearrangeCode()) { processor = new RearrangeCodeProcessor(processor); } @@ -306,23 +399,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } } - public static void updateShowDialogSetting(LayoutCodeDialog dialog, String title) { - if (dialog.isDoNotAskMe()) { - Notifications.Bus.notify(new Notification("Reformat Code", title, - "You can re-enable the dialog on the IDE Settings -> Editor pane", - NotificationType.INFORMATION, new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - final ShowSettingsUtil util = ShowSettingsUtil.getInstance(); - IdeFrame ideFrame = WindowManagerEx.getInstanceEx().findFrameFor(null); - util.editConfigurable((JFrame)ideFrame, new EditorOptions()); - } - } - })); - } - } - public static PsiFile[] convertToPsiFiles(final VirtualFile[] files,Project project) { final PsiManager manager = PsiManager.getInstance(project); final ArrayList result = new ArrayList(); @@ -434,24 +510,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return dialog; } - @Nullable - private static LayoutCodeOptions getLayoutCodeOptions(@NotNull Project project, - @Nullable PsiFile file, - @Nullable PsiDirectory dir, - boolean hasSelection) { - if (ApplicationManager.getApplication().isUnitTestMode()) { - return (LayoutCodeOptions)myTestOptions; - } - LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), - file, dir, hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID); - if (!dialog.showAndGet()) { - return null; - } - EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = !dialog.isDoNotAskMe(); - updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled"); - return dialog; - } - public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) { if (file != null) { return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java new file mode 100644 index 000000000000..5f1060ed01ff --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java @@ -0,0 +1,81 @@ +/* + * 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.codeInsight.actions; + +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NonNls; + +public class ReformatFileAction extends AnAction implements DumbAware { + private static final @NonNls String HELP_ID = "editing.codeReformatting"; + + @Override + public void update(AnActionEvent event) { + Presentation presentation = event.getPresentation(); + DataContext dataContext = event.getDataContext(); + Project project = CommonDataKeys.PROJECT.getData(dataContext); + Editor editor = CommonDataKeys.EDITOR.getData(dataContext); + if (project == null || editor == null) { + presentation.setEnabled(false); + return; + } + + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file == null || file.getVirtualFile() == null) { + presentation.setEnabled(false); + return; + } + + //todo if we can do something with it then + + presentation.setEnabled(true); + } + + @Override + public void actionPerformed(AnActionEvent event) { + Presentation presentation = event.getPresentation(); + DataContext dataContext = event.getDataContext(); + Project project = CommonDataKeys.PROJECT.getData(dataContext); + Editor editor = CommonDataKeys.EDITOR.getData(dataContext); + if (project == null || editor == null) { + presentation.setEnabled(false); + return; + } + + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file == null || file.getVirtualFile() == null) { + presentation.setEnabled(false); + return; + } + + boolean hasSelection = editor.getSelectionModel().hasSelection(); + LayoutCodeDialog dialog = new LayoutCodeDialog(project, file, hasSelection, HELP_ID); + dialog.show(); + + if (!dialog.isOK()) return; + + //new LayoutCodeProcessorBuilder(project, editor, file) + // .setReformatCode(dialog.isReformatCode()) + // .setOptimizeImports(dialog.isOptimizeImports()) + // .setRearrangeCode(dialog.isRearrangeCode()) + // .setTextRangeType(dialog.getTextRangeType()) + // .processCode(); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java index d364857352e6..c7835e69b353 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java @@ -27,6 +27,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; +import static com.intellij.codeInsight.actions.TextRangeType.*; + public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesOptions { @NotNull private Project myProject; private JPanel myPanel; @@ -60,12 +62,14 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO } @Override - public boolean isProcessOnlyChangedText() { - return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected(); + public TextRangeType getTextRangeType() { + return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected() + ? VCS_CHANGED_TEXT + : WHOLE_FILE; } @Override - public boolean isRearrangeEntries() { + public boolean isRearrangeCode() { return myRearrangeEntriesCb.isSelected(); } @@ -74,7 +78,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO super.doOKAction(); PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected())); PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected())); - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries()); + LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeCode()); } static boolean isOptmizeImportsOptionOn() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java index bb958e77b2fe..f10757940324 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java @@ -18,13 +18,7 @@ package com.intellij.codeInsight.actions; import com.intellij.psi.search.SearchScope; import org.jetbrains.annotations.Nullable; -public interface ReformatFilesOptions { - - boolean isOptimizeImports(); - - boolean isProcessOnlyChangedText(); - - boolean isRearrangeEntries(); +public interface ReformatFilesOptions extends LayoutCodeOptions { @Nullable String getFileTypeMask(); diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 8cd7594ebaaa..107cfd8b76a6 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -87,6 +87,9 @@ + + + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 2f1324ba9702..412f376cef1b 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -930,5 +930,7 @@ + +
From 9693c6ae52a9590fc77ec35f0ca52356cdfff9be Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 23 Dec 2014 20:56:50 +0200 Subject: [PATCH 005/231] unified last run reformat code options into LastRunReformatCodeOptionProvider --- .../AbstractLayoutCodeProcessorTest.java | 32 +------- .../actions/ReformatCodeActionTest.java | 56 +------------- .../LastRunReformatCodeOptionsProvider.java | 77 +++++++++++++++++++ .../actions/LayoutCodeConstants.java | 32 -------- .../codeInsight/actions/LayoutCodeDialog.java | 34 ++++---- .../actions/LayoutCodeSettingsStorage.java | 50 ------------ .../actions/LayoutProjectCodeDialog.java | 14 ++-- .../actions/OptimizeImportsAction.java | 7 +- .../actions/ReformatCodeAction.java | 46 ++++++----- .../actions/ReformatFilesDialog.java | 30 ++++---- 10 files changed, 151 insertions(+), 227 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java delete mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java delete mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java index f1cab2fe1188..e170e2a78da8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java @@ -318,14 +318,8 @@ class AdditionalEventInfo { } class MockReformatFileSettings implements ReformatFilesOptions { - private boolean myProcessWholeFile; - private boolean myProcessDirectories; - private boolean myRearrange; - private boolean myIncludeSubdirs; private boolean myOptimizeImports; - private boolean myProcessOnlyChangedText; - private boolean myIsOK = true; - private TextRangeType myTextRangeType; + private boolean myIncludeSubdirs; @Nullable @Override @@ -339,28 +333,14 @@ class MockReformatFileSettings implements ReformatFilesOptions { return null; } - MockReformatFileSettings setProcessWholeFile(boolean processWholeFile) { - myProcessWholeFile = processWholeFile; - return this; - } - - MockReformatFileSettings setProcessDirectory(boolean processDirectories) { - myProcessDirectories = processDirectories; - return this; - } - @Override public TextRangeType getTextRangeType() { - return null; - } - - public void setTextRangeType(TextRangeType textRangeType) { - myTextRangeType = textRangeType; + return TextRangeType.WHOLE_FILE; } @Override public boolean isRearrangeCode() { - return myRearrange; + return false; } @Override @@ -374,12 +354,6 @@ class MockReformatFileSettings implements ReformatFilesOptions { return this; } - @NotNull - MockReformatFileSettings setRearrange(boolean rearrange) { - myRearrange = rearrange; - return this; - } - @NotNull MockReformatFileSettings setIncludeSubdirs(boolean includeSubdirs) { myIncludeSubdirs = includeSubdirs; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index f2cd858132db..afd89fa229fd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -40,16 +40,8 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkFormationAndImportsOptimizationFor(files); } - public void testReformatSingleSelectedFile() throws IOException { - List files = createTestFiles(getTempRootDirectory(), classNames); - PsiFile fileToReformat = files.get(0); - List shouldNotBeFormatted = files.subList(1, files.size()); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); - - performReformatActionOnSelectedFile(fileToReformat); - - checkFormationAndImportsOptimizationFor(Arrays.asList(fileToReformat)); - checkNoProcessingWasPerformedOn(shouldNotBeFormatted); + public void testReformatSingleSelected_FileWithoutEditor() throws IOException { + //todo fill } public void testReformatAndOptimizeFileFromEditor() throws IOException { @@ -77,26 +69,8 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkNoProcessingWasPerformedOn(noProcessing); } - public void testOptimizeAndReformatAllFilesInDirectoryIncludeSubdirs() throws IOException { - TestFileStructure fileStructure = getThreeLevelDirectoryStructure(); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setProcessDirectory(true).setIncludeSubdirs(true)); - PsiFile fileInEditor = fileStructure.getFilesAtLevel(2).get(0); - List shouldNotBeFormatted = fileStructure.getFilesAtLevel(1); - - performReformatActionOnFileInEditor(fileInEditor); - - checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2), fileStructure.getFilesAtLevel(3)); - checkNoProcessingWasPerformedOn(shouldNotBeFormatted); - } - - public void testOptimizeAndReformatAllFilesInDirectoryExcludeSubdirs() throws IOException { - TestFileStructure fileStructure = getThreeLevelDirectoryStructure(); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setIncludeSubdirs(false)); - - performReformatActionOnSelectedFiles(fileStructure.getFilesAtLevel(2)); - - checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2)); - checkNoProcessingWasPerformedOn(fileStructure.getFilesAtLevel(1), fileStructure.getFilesAtLevel(3)); + public void testOptimizeAndReformat_AllFilesInDirectoryIncludeSubdirs() throws IOException { + //todo create tests for AbstractLayoutCodeProcessor } public void testOptimizeAndReformatInModule() throws IOException { @@ -109,26 +83,4 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkFormationAndImportsOptimizationFor(files); } - - private TestFileStructure getThreeLevelDirectoryStructure() throws IOException { - TestFileStructure fileStructure = new TestFileStructure(getModule(), getTempRootDirectory()); - - fileStructure.createDirectoryAndMakeItCurrent("dir"); - addFilesToCurrentDirectory(fileStructure); - - fileStructure.createDirectoryAndMakeItCurrent("innerDir"); - addFilesToCurrentDirectory(fileStructure); - - fileStructure.createDirectoryAndMakeItCurrent("innerInnerDir"); - addFilesToCurrentDirectory(fileStructure); - - return fileStructure; - } - - private void addFilesToCurrentDirectory(TestFileStructure fileStructure) throws IOException { - for (int i = 0; i < 5; i++) { - String className = "Test" + i; - fileStructure.addTestFile("Test" + i + ".java", getUntouchedJavaSourceForTotalProcessing(className)); - } - } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java new file mode 100644 index 000000000000..8ba3f5e511b5 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java @@ -0,0 +1,77 @@ +/* + * 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.codeInsight.actions; + +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.lang.Language; +import org.jetbrains.annotations.NotNull; + +public class LastRunReformatCodeOptionsProvider implements LayoutCodeOptions { + + private static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports"; + private static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries"; + private static final String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText"; + + private final PropertiesComponent myPropertiesComponent; + + public LastRunReformatCodeOptionsProvider(@NotNull PropertiesComponent propertiesComponent) { + myPropertiesComponent = propertiesComponent; + } + + public void saveRearrangeState(@NotNull Language language, boolean value) { + String key = getRearrangeCodeKeyFor(language); + myPropertiesComponent.setValue(key, Boolean.toString(value)); + } + + public void saveOptimizeImportsState(boolean value) { + String optimizeImports = Boolean.toString(value); + myPropertiesComponent.setValue(OPTIMIZE_IMPORTS_KEY, optimizeImports); + } + + @Override + public boolean isOptimizeImports() { + return myPropertiesComponent.getBoolean(OPTIMIZE_IMPORTS_KEY, false); + } + + @Override + public TextRangeType getTextRangeType() { + return myPropertiesComponent.getBoolean(PROCESS_CHANGED_TEXT_KEY, false) ? TextRangeType.VCS_CHANGED_TEXT : TextRangeType.WHOLE_FILE; + } + + public void saveProcessVcsChangedTextState(boolean value) { + String processOnlyVcsChangedText = Boolean.toString(value); + myPropertiesComponent.setValue(PROCESS_CHANGED_TEXT_KEY, processOnlyVcsChangedText); + } + + public void saveRearrangeCodeState(boolean value) { + myPropertiesComponent.setValue(REARRANGE_ENTRIES_KEY, Boolean.toString(value)); + } + + @Override + public boolean isRearrangeCode() { + return myPropertiesComponent.getBoolean(REARRANGE_ENTRIES_KEY, false); + } + + public boolean isRearrangeCode(@NotNull Language language) { + String key = getRearrangeCodeKeyFor(language); + return myPropertiesComponent.getBoolean(key, false); + } + + private static String getRearrangeCodeKeyFor(@NotNull Language language) { + return REARRANGE_ENTRIES_KEY + language.getDisplayName(); + } + +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java deleted file mode 100644 index 84de47d7f457..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeConstants.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInsight.actions; - -import org.jetbrains.annotations.NonNls; - -/** - * @author Denis Zhdanov - * @since 12/16/11 6:10 PM - */ -public class LayoutCodeConstants { - - @NonNls public static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports"; - @NonNls public static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries"; - @NonNls public static final String PROCESS_CHANGED_TEXT_KEY = "LayoutCode.processChangedText"; - - private LayoutCodeConstants() { - } -} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 177461c4cf6a..8fd158b54b45 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -31,8 +31,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; -import static com.intellij.codeInsight.actions.ReformatCodeAction.getLastSavedRearrangeCbState; - public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions { @NotNull private final Project myProject; @NotNull private final PsiFile myFile; @@ -40,10 +38,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions private final boolean myTextSelected; private final String myHelpId; - - private boolean myLastRunOptimizeImportsWasEnabled; - private boolean myLastRunOnlyVcsChangedTextEnabled; - private boolean myLastRunRearrangeWasEnabled; + private final LastRunReformatCodeOptionsProvider myLastRunOptions; private JPanel myButtonsPanel; @@ -67,9 +62,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions myTextSelected = textSelected; myHelpId = helpId; - myLastRunOptimizeImportsWasEnabled = ReformatFilesDialog.isOptmizeImportsOptionOn(); - myLastRunRearrangeWasEnabled = getLastSavedRearrangeCbState(project, file); - myLastRunOnlyVcsChangedTextEnabled = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); + myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle("Reformat File: " + file.getName()); @@ -118,11 +111,14 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions if (myTextSelected) { mySelectedTextRadioButton.setSelected(true); } - else if (myLastRunOnlyVcsChangedTextEnabled && fileHasChanges) { - myOnlyVCSChangedTextRb.setSelected(true); - } else { - myWholeFileRadioButton.setSelected(true); + boolean lastRunProcessedChangedText = myLastRunOptions.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; + if (lastRunProcessedChangedText && fileHasChanges) { + myOnlyVCSChangedTextRb.setSelected(true); + } + else { + myWholeFileRadioButton.setSelected(true); + } } } @@ -130,13 +126,13 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions boolean canOptimizeImports = !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty(); myOptimizeImportsCb.setVisible(canOptimizeImports); if (canOptimizeImports) { - myOptimizeImportsCb.setSelected(myLastRunOptimizeImportsWasEnabled); + myOptimizeImportsCb.setSelected(myLastRunOptions.isOptimizeImports()); } boolean canRearrangeCode = Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; myRearrangeCodeCb.setVisible(canRearrangeCode); if (canRearrangeCode) { - myRearrangeCodeCb.setSelected(myLastRunRearrangeWasEnabled); + myRearrangeCodeCb.setSelected(myLastRunOptions.isRearrangeCode(myFile.getLanguage())); } } @@ -153,16 +149,14 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions private void saveCurrentConfiguration() { if (myOptimizeImportsCb.isEnabled()) { - String optimizeImports = Boolean.toString(isOptimizeImports()); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, optimizeImports); + myLastRunOptions.saveOptimizeImportsState(isOptimizeImports()); } if (myRearrangeCodeCb.isEnabled()) { - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, myFile.getLanguage(), isRearrangeCode()); + myLastRunOptions.saveRearrangeState(myFile.getLanguage(), isRearrangeCode()); } if (!mySelectedTextRadioButton.isSelected()) { - String formatVcsChangedRegions = Boolean.toString(myOnlyVCSChangedTextRb.isSelected()); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, formatVcsChangedRegions); + myLastRunOptions.saveProcessVcsChangedTextState(myOnlyVCSChangedTextRb.isSelected()); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java deleted file mode 100644 index 5175cf522556..000000000000 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeSettingsStorage.java +++ /dev/null @@ -1,50 +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.codeInsight.actions; - -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.lang.Language; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -public class LayoutCodeSettingsStorage { - - private LayoutCodeSettingsStorage() { - } - - public static void saveRearrangeEntriesOptionFor(@NotNull Project project, @NotNull Language language, boolean value) { - String key = getRearrangeEntriesKeyForLanguage(language); - PropertiesComponent.getInstance(project).setValue(key, Boolean.toString(value)); - } - - public static void saveRearrangeEntriesOptionFor(@NotNull Project project, boolean value) { - PropertiesComponent.getInstance(project).setValue(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, Boolean.toString(value)); - } - - public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project) { - return PropertiesComponent.getInstance(project).getBoolean(LayoutCodeConstants.REARRANGE_ENTRIES_KEY, false); - } - - public static boolean getLastSavedRearrangeEntriesCbStateFor(@NotNull Project project, @NotNull Language language) { - String key = getRearrangeEntriesKeyForLanguage(language); - return PropertiesComponent.getInstance(project).getBoolean(key, false); - } - - private static String getRearrangeEntriesKeyForLanguage(@NotNull Language language) { - return LayoutCodeConstants.REARRANGE_ENTRIES_KEY + language.getDisplayName(); - } - -} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java index f6964417ac56..7bab9232535a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java @@ -47,6 +47,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi private final Project myProject; private final String myText; private final boolean myEnableOnlyVCSChangedTextCb; + private final LastRunReformatCodeOptionsProvider myLastRunOptions; private JLabel myTitle; protected JCheckBox myIncludeSubdirsCb; @@ -75,6 +76,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi myText = text; myProject = project; myEnableOnlyVCSChangedTextCb = enableOnlyVCSChangedTextCb; + myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(title); @@ -100,11 +102,11 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi } private void restoreCbsStates() { - myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false)); - myCbRearrangeEntries.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); + myCbOptimizeImports.setSelected(myLastRunOptions.isOptimizeImports()); + myCbRearrangeEntries.setSelected(myLastRunOptions.isRearrangeCode()); myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb); myCbOnlyVcsChangedRegions.setSelected( - myEnableOnlyVCSChangedTextCb && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) + myEnableOnlyVCSChangedTextCb && myLastRunOptions.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT ); } @@ -189,10 +191,10 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi @Override protected void doOKAction() { super.doOKAction(); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports())); - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeCode()); + myLastRunOptions.saveOptimizeImportsState(isOptimizeImports()); + myLastRunOptions.saveRearrangeCodeState(isRearrangeCode()); if (myEnableOnlyVCSChangedTextCb) { - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected())); + myLastRunOptions.saveProcessVcsChangedTextState(getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java index 5eb588e6d5fd..4ed258297f06 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java @@ -200,14 +200,17 @@ public class OptimizeImportsAction extends AnAction { } private static class OptimizeImportsDialog extends DialogWrapper { - private final String myText; private final boolean myContextHasChanges; + + private final String myText; private JCheckBox myOnlyVcsCheckBox; + private final LastRunReformatCodeOptionsProvider myLastRunOptions; OptimizeImportsDialog(Project project, String text, boolean hasChanges) { super(project, false); myText = text; myContextHasChanges = hasChanges; + myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle(CodeInsightBundle.message("process.optimize.imports")); init(); @@ -227,7 +230,7 @@ public class OptimizeImportsAction extends AnAction { panel.add(new JLabel(myText)); myOnlyVcsCheckBox = new JCheckBox("only VCS changed files"); - boolean lastRunVcsChangedTextEnabled = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); + boolean lastRunVcsChangedTextEnabled = myLastRunOptions.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; myOnlyVcsCheckBox.setEnabled(myContextHasChanges); myOnlyVcsCheckBox.setSelected(myContextHasChanges && lastRunVcsChangedTextEnabled); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index 348de0668dbc..8c387957eccd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -135,9 +135,17 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } } - final boolean optimizeImports = ReformatFilesDialog.isOptmizeImportsOptionOn(); - boolean processChangedTextOnly = PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false); - final boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file); + LayoutCodeOptions lastRunOptions = getLastRunReformatCodeOptions(); + TextRangeType processingType = lastRunOptions.getTextRangeType(); + final boolean optimizeImports = lastRunOptions.isOptimizeImports(); + final boolean rearrangeEntries; + if (file != null && lastRunOptions instanceof LastRunReformatCodeOptionsProvider) { + LastRunReformatCodeOptionsProvider options = (LastRunReformatCodeOptionsProvider)lastRunOptions; + rearrangeEntries = options.isRearrangeCode(file.getLanguage()); + } + else { + rearrangeEntries = lastRunOptions.isRearrangeCode(); + } if (file == null && dir != null) { DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir); @@ -147,28 +155,26 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return; } + //todo let when editor == null proceed and perform if (file == null || editor == null) return; TextRange range = null; - TextRangeType textRangeType; if (hasSelection) { - processChangedTextOnly = false; - textRangeType = TextRangeType.SELECTED_TEXT; + processingType = TextRangeType.SELECTED_TEXT; SelectionModel model = editor.getSelectionModel(); range = TextRange.create(model.getSelectionStart(), model.getSelectionEnd()); } - else if (processChangedTextOnly) { - textRangeType = TextRangeType.VCS_CHANGED_TEXT; - + else if (processingType == TextRangeType.VCS_CHANGED_TEXT) { if (isChangeNotTrackedForFile(project, file)) { - textRangeType = TextRangeType.WHOLE_FILE; - processChangedTextOnly = false; + processingType = TextRangeType.WHOLE_FILE; } } else { - textRangeType = TextRangeType.WHOLE_FILE; + processingType = TextRangeType.WHOLE_FILE; } + boolean processChangedTextOnly = processingType == TextRangeType.VCS_CHANGED_TEXT; + AbstractLayoutCodeProcessor processor; if (optimizeImports && range == null) { processor = new OptimizeImportsProcessor(project, file); @@ -186,7 +192,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { final CharSequence charSeqBefore = document != null ? document.getImmutableCharSequence() : null; final PsiFile finalFile = file; - final TextRangeType finalTextRangeType = textRangeType; + final TextRangeType finalTextRangeType = processingType; //todo show it if available options =) @@ -510,13 +516,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return dialog; } - public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) { - if (file != null) { - return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage()); - } - return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project); - } - @TestOnly protected static void setTestOptions(ReformatFilesOptions options) { myTestOptions = options; @@ -530,6 +529,13 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } return true; } + + public LayoutCodeOptions getLastRunReformatCodeOptions() { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return myTestOptions; + } + return new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java index c7835e69b353..7b17da453cd0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java @@ -30,24 +30,24 @@ import javax.swing.*; import static com.intellij.codeInsight.actions.TextRangeType.*; public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesOptions { - @NotNull private Project myProject; private JPanel myPanel; private JCheckBox myOptimizeImports; private JCheckBox myOnlyChangedText; private JCheckBox myRearrangeEntriesCb; + private final LastRunReformatCodeOptionsProvider myLastRunSettings; + public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) { super(project, true); - myProject = project; - setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); - myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); + myLastRunSettings = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + boolean canTargetVcsChanges = FormatChangedTextUtil.hasChanges(files, project); myOnlyChangedText.setEnabled(canTargetVcsChanges); - myOnlyChangedText.setSelected( - canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false) - ); - myOptimizeImports.setSelected(isOptmizeImportsOptionOn()); - myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject)); + myOnlyChangedText.setSelected(canTargetVcsChanges && myLastRunSettings.getTextRangeType() == VCS_CHANGED_TEXT); + myOptimizeImports.setSelected(myLastRunSettings.isOptimizeImports()); + myRearrangeEntriesCb.setSelected(myLastRunSettings.isRearrangeCode()); + + setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); init(); } @@ -76,13 +76,11 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO @Override protected void doOKAction() { super.doOKAction(); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected())); - PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected())); - LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeCode()); - } - - static boolean isOptmizeImportsOptionOn() { - return PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false); + myLastRunSettings.saveOptimizeImportsState(isOptimizeImports()); + myLastRunSettings.saveRearrangeCodeState(isRearrangeCode()); + if (myOnlyChangedText.isEnabled()) { + myLastRunSettings.saveProcessVcsChangedTextState(getTextRangeType() == VCS_CHANGED_TEXT); + } } @Nullable From d923d55d24f64cfbdec9564b21c2463858b3cf09 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 01:50:35 +0200 Subject: [PATCH 006/231] FormatChangedTextUtil: passing document instead of PsiFile --- .../actions/FormatChangedTextUtil.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index aca2397c531f..af8df3ddd317 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -246,7 +246,10 @@ public class FormatChangedTextUtil { @NotNull public static List getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) throws FilesTooBigForDiffException { - List cachedChangedLines = getCachedChangedLines(project, file); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + if (document == null) return ContainerUtil.emptyList(); + + List cachedChangedLines = getCachedChangedLines(project, document); if (cachedChangedLines != null) { return cachedChangedLines; } @@ -260,17 +263,12 @@ public class FormatChangedTextUtil { } String contentFromVcs = getRevisionedContentFrom(change); - return contentFromVcs != null ? calculateChangedTextRanges(project, file, contentFromVcs) + return contentFromVcs != null ? calculateChangedTextRanges(document, contentFromVcs) : ContainerUtil.emptyList(); } @Nullable - private static List getCachedChangedLines(@NotNull Project project, @NotNull PsiFile file) { - Document document = PsiDocumentManager.getInstance(project).getDocument(file); - if (document == null) { - return ContainerUtil.emptyList(); - } - + private static List getCachedChangedLines(@NotNull Project project, @NotNull Document document) { LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(document); if (tracker != null) { List ranges = tracker.getRanges(); @@ -297,17 +295,10 @@ public class FormatChangedTextUtil { } @NotNull - protected static List calculateChangedTextRanges(@NotNull Project project, - @NotNull PsiFile file, + protected static List calculateChangedTextRanges(@NotNull Document document, @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException { Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false); - Document document = PsiDocumentManager.getInstance(project).getDocument(file); - - if (document == null) { - return ContainerUtil.emptyList(); - } - List changedRanges = new RangesBuilder(document, documentFromVcs).getRanges(); return getChangedTextRanges(document, changedRanges); } From 7f7fc973a2f2db0641afc9f7970db2a258cdd2d0 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 02:28:51 +0200 Subject: [PATCH 007/231] Extracted processor creating logic into CodeProcessor, refactorings --- .../actions/ReformatCodeActionTest.java | 4 +- .../codeInsight/actions/CodeProcessor.java | 168 ++++++++++++++++++ .../actions/FormatChangedTextUtil.java | 21 +-- .../LastRunReformatCodeOptionsProvider.java | 22 ++- .../codeInsight/actions/LayoutCodeDialog.java | 4 +- .../actions/LayoutProjectCodeDialog.java | 6 +- .../actions/OptimizeImportsAction.java | 2 +- .../actions/RearrangeCodeProcessor.java | 7 +- .../actions/ReformatCodeAction.java | 148 ++------------- .../actions/ReformatCodeRunOptions.java | 56 ++++++ .../actions/ReformatFilesDialog.java | 6 +- 11 files changed, 271 insertions(+), 173 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index afd89fa229fd..20b483c9b077 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -34,7 +34,9 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { public void testReformatAndOptimizeMultipleFiles() throws IOException { List files = createTestFiles(getTempRootDirectory(), classNames); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); + + //todo mock this guy + //LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); performReformatActionOnSelectedFiles(files); checkFormationAndImportsOptimizationFor(files); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java new file mode 100644 index 000000000000..d6f17dc8f341 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -0,0 +1,168 @@ +/* + * 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.codeInsight.actions; + +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.hint.HintManagerImpl; +import com.intellij.codeInsight.hint.HintUtil; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; +import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.ui.LightweightHint; +import com.intellij.util.diff.FilesTooBigForDiffException; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.List; + +import static com.intellij.codeInsight.actions.TextRangeType.*; + +class CodeProcessor { + private final Editor myEditor; + + private final boolean myShouldOptimizeImports; + private final boolean myShouldRearrangeCode; + private final boolean myProcessSelectedText; + private final boolean myProcessChangesTextOnly; + private final boolean myShouldNotify; + + private final Project myProject; + private final PsiFile myFile; + private final TextRangeType myProcessingType; + + public CodeProcessor(PsiFile file, + Editor editor, + ReformatCodeRunOptions reformatCodeRunOptions) + { + myFile = file; + myProject = file.getProject(); + myEditor = editor; + + myProcessingType = reformatCodeRunOptions.getTextRangeType(); + + myShouldOptimizeImports = reformatCodeRunOptions.isOptimizeImports(); + myShouldRearrangeCode = reformatCodeRunOptions.isRearrangeCode(); + myProcessSelectedText = reformatCodeRunOptions.getTextRangeType() == SELECTED_TEXT; + myProcessChangesTextOnly = reformatCodeRunOptions.getTextRangeType() == VCS_CHANGED_TEXT; + + myShouldNotify = editor != null && !myProcessSelectedText; + } + + public void processCode() { + AbstractLayoutCodeProcessor processor; + if (myShouldOptimizeImports) { + processor = new OptimizeImportsProcessor(myProject, myFile); + new ReformatCodeProcessor(processor, myProcessChangesTextOnly); + } + else { + SelectionModel model = myEditor.getSelectionModel(); + TextRange range = myProcessSelectedText && model.hasSelection() + ? new TextRange(model.getSelectionStart(), model.getSelectionEnd()) + : null; + + processor = new ReformatCodeProcessor(myProject, myFile, range, false); + } + + if (myShouldRearrangeCode) { + if (myProcessSelectedText) { + processor = new RearrangeCodeProcessor(processor, myEditor.getSelectionModel()); + } + else { + processor = new RearrangeCodeProcessor(processor); + } + } + + if (myShouldNotify) { + final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myFile); + final CharSequence textBeforeChange = document != null ? document.getImmutableCharSequence() : null; + processor.setPostRunnable(new Runnable() { + @Override + public void run() { + if (document != null) { + String info = prepareMessage(document, textBeforeChange); + showHint(myEditor, info); + } + } + }); + } + + processor.run(); + } + + private int getProcessedLinesNumber(final Document document, final CharSequence before) { + int totalLinesProcessed = 0; + try { + List ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before); + for (TextRange range : ranges) { + int lineStartNumber = document.getLineNumber(range.getStartOffset()); + int lineEndNumber = document.getLineNumber(range.getEndOffset()); + + totalLinesProcessed += lineEndNumber - lineStartNumber + 1; + } + } + catch (FilesTooBigForDiffException e) { + return -1; + } + return totalLinesProcessed; + } + + @NotNull + private String prepareMessage(@NotNull Document document, @NotNull CharSequence textBeforeChange) { + int totalLinesProcessed = getProcessedLinesNumber(document, textBeforeChange); + + String linesInfo = ""; + if (totalLinesProcessed >= 0) { + linesInfo = "Changed " + totalLinesProcessed + " lines"; + } + + String scopeInfo = myProcessingType == VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null; + String actionsInfo = "Performed: formatting"; + if (myShouldOptimizeImports) { + actionsInfo += ", import optimization"; + } + if (myShouldRearrangeCode) { + actionsInfo += " and code rearrangement"; + } + + String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); + + String info = linesInfo; + if (scopeInfo != null) { + info += scopeInfo; + } + info += "\n"; + info += actionsInfo + "\n"; + info += shortcutInfo; + + return info; + } + + private void showHint(@NotNull Editor editor, @NotNull String info) { + JComponent component = HintUtil.createInformationLabel(info); + LightweightHint hint = new LightweightHint(component); + HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, + HintManager.HIDE_BY_ANY_KEY | + HintManager.HIDE_BY_TEXT_CHANGE | + HintManager.HIDE_BY_SCROLLING, + 0, false); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index af8df3ddd317..b3dfef2bcb2a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -68,26 +68,9 @@ public class FormatChangedTextUtil { final VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null) { final Change change = ChangeListManager.getInstance(project).getChange(virtualFile); - if (change != null && change.getType() == Change.Type.NEW) { - return true; - } + return change != null; } - - final LineStatusTrackerManagerI manager = LineStatusTrackerManager.getInstance(project); - if (manager == null) { - return false; - } - - final Document document = PsiDocumentManager.getInstance(project).getDocument(file); - if (document == null) { - return false; - } - final LineStatusTracker lineStatusTracker = manager.getLineStatusTracker(document); - if (lineStatusTracker == null) { - return false; - } - final List ranges = lineStatusTracker.getRanges(); - return !ranges.isEmpty(); + return false; } /** diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java index 8ba3f5e511b5..9ba882fba3e3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LastRunReformatCodeOptionsProvider.java @@ -17,9 +17,10 @@ package com.intellij.codeInsight.actions; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.Language; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -public class LastRunReformatCodeOptionsProvider implements LayoutCodeOptions { +public class LastRunReformatCodeOptionsProvider { private static final String OPTIMIZE_IMPORTS_KEY = "LayoutCode.optimizeImports"; private static final String REARRANGE_ENTRIES_KEY = "LayoutCode.rearrangeEntries"; @@ -31,6 +32,16 @@ public class LastRunReformatCodeOptionsProvider implements LayoutCodeOptions { myPropertiesComponent = propertiesComponent; } + public ReformatCodeRunOptions getLastRunOptions(@NotNull PsiFile file) { + Language language = file.getLanguage(); + + ReformatCodeRunOptions settings = new ReformatCodeRunOptions(getLastTextRangeType()); + settings.setOptimizeImports(getLastOptimizeImports()); + settings.setRearrangeCode(isRearrangeCode(language)); + + return settings; + } + public void saveRearrangeState(@NotNull Language language, boolean value) { String key = getRearrangeCodeKeyFor(language); myPropertiesComponent.setValue(key, Boolean.toString(value)); @@ -41,13 +52,11 @@ public class LastRunReformatCodeOptionsProvider implements LayoutCodeOptions { myPropertiesComponent.setValue(OPTIMIZE_IMPORTS_KEY, optimizeImports); } - @Override - public boolean isOptimizeImports() { + public boolean getLastOptimizeImports() { return myPropertiesComponent.getBoolean(OPTIMIZE_IMPORTS_KEY, false); } - @Override - public TextRangeType getTextRangeType() { + public TextRangeType getLastTextRangeType() { return myPropertiesComponent.getBoolean(PROCESS_CHANGED_TEXT_KEY, false) ? TextRangeType.VCS_CHANGED_TEXT : TextRangeType.WHOLE_FILE; } @@ -60,8 +69,7 @@ public class LastRunReformatCodeOptionsProvider implements LayoutCodeOptions { myPropertiesComponent.setValue(REARRANGE_ENTRIES_KEY, Boolean.toString(value)); } - @Override - public boolean isRearrangeCode() { + public boolean getLastRearrangeCode() { return myPropertiesComponent.getBoolean(REARRANGE_ENTRIES_KEY, false); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 8fd158b54b45..36bbf8751a58 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -112,7 +112,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions mySelectedTextRadioButton.setSelected(true); } else { - boolean lastRunProcessedChangedText = myLastRunOptions.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; + boolean lastRunProcessedChangedText = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; if (lastRunProcessedChangedText && fileHasChanges) { myOnlyVCSChangedTextRb.setSelected(true); } @@ -126,7 +126,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions boolean canOptimizeImports = !LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty(); myOptimizeImportsCb.setVisible(canOptimizeImports); if (canOptimizeImports) { - myOptimizeImportsCb.setSelected(myLastRunOptions.isOptimizeImports()); + myOptimizeImportsCb.setSelected(myLastRunOptions.getLastOptimizeImports()); } boolean canRearrangeCode = Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java index 7bab9232535a..7690e09339f8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java @@ -102,11 +102,11 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi } private void restoreCbsStates() { - myCbOptimizeImports.setSelected(myLastRunOptions.isOptimizeImports()); - myCbRearrangeEntries.setSelected(myLastRunOptions.isRearrangeCode()); + myCbOptimizeImports.setSelected(myLastRunOptions.getLastOptimizeImports()); + myCbRearrangeEntries.setSelected(myLastRunOptions.getLastRearrangeCode()); myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb); myCbOnlyVcsChangedRegions.setSelected( - myEnableOnlyVCSChangedTextCb && myLastRunOptions.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT + myEnableOnlyVCSChangedTextCb && myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT ); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java index 4ed258297f06..8045e9f2b063 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java @@ -230,7 +230,7 @@ public class OptimizeImportsAction extends AnAction { panel.add(new JLabel(myText)); myOnlyVcsCheckBox = new JCheckBox("only VCS changed files"); - boolean lastRunVcsChangedTextEnabled = myLastRunOptions.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; + boolean lastRunVcsChangedTextEnabled = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; myOnlyVcsCheckBox.setEnabled(myContextHasChanges); myOnlyVcsCheckBox.setSelected(myContextHasChanges && lastRunVcsChangedTextEnabled); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index b34fcb858108..4d765aa2ab9a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -45,7 +45,12 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); } - + + public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel model) { + super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); + mySelectionModel = model; + } + public RearrangeCodeProcessor(@NotNull Project project, @NotNull PsiFile file, @Nullable SelectionModel selectionModel) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index 8c387957eccd..7b0422fd2475 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -17,9 +17,6 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.HintManagerImpl; -import com.intellij.codeInsight.hint.HintUtil; import com.intellij.find.impl.FindInProjectUtil; import com.intellij.formatting.FormattingModelBuilder; import com.intellij.ide.util.PropertiesComponent; @@ -27,15 +24,11 @@ import com.intellij.lang.LanguageFormatting; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; -import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; @@ -44,15 +37,12 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiUtilCore; -import com.intellij.ui.LightweightHint; -import com.intellij.util.diff.FilesTooBigForDiffException; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import javax.swing.*; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -135,18 +125,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } } - LayoutCodeOptions lastRunOptions = getLastRunReformatCodeOptions(); - TextRangeType processingType = lastRunOptions.getTextRangeType(); - final boolean optimizeImports = lastRunOptions.isOptimizeImports(); - final boolean rearrangeEntries; - if (file != null && lastRunOptions instanceof LastRunReformatCodeOptionsProvider) { - LastRunReformatCodeOptionsProvider options = (LastRunReformatCodeOptionsProvider)lastRunOptions; - rearrangeEntries = options.isRearrangeCode(file.getLanguage()); - } - else { - rearrangeEntries = lastRunOptions.isRearrangeCode(); - } - if (file == null && dir != null) { DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir); if (options != null) { @@ -155,14 +133,14 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return; } - //todo let when editor == null proceed and perform if (file == null || editor == null) return; - TextRange range = null; + LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + ReformatCodeRunOptions currentRunOptions = provider.getLastRunOptions(file); + + TextRangeType processingType = currentRunOptions.getTextRangeType(); if (hasSelection) { processingType = TextRangeType.SELECTED_TEXT; - SelectionModel model = editor.getSelectionModel(); - range = TextRange.create(model.getSelectionStart(), model.getSelectionEnd()); } else if (processingType == TextRangeType.VCS_CHANGED_TEXT) { if (isChangeNotTrackedForFile(project, file)) { @@ -172,111 +150,9 @@ public class ReformatCodeAction extends AnAction implements DumbAware { else { processingType = TextRangeType.WHOLE_FILE; } + currentRunOptions.setProcessingScope(processingType); - boolean processChangedTextOnly = processingType == TextRangeType.VCS_CHANGED_TEXT; - - AbstractLayoutCodeProcessor processor; - if (optimizeImports && range == null) { - processor = new OptimizeImportsProcessor(project, file); - processor = new ReformatCodeProcessor(processor, processChangedTextOnly); - } - else { - processor = new ReformatCodeProcessor(project, file, range, processChangedTextOnly); - } - - if (rearrangeEntries) { - processor = new RearrangeCodeProcessor(processor); - } - - final Document document = PsiDocumentManager.getInstance(project).getDocument(file); - final CharSequence charSeqBefore = document != null ? document.getImmutableCharSequence() : null; - - final PsiFile finalFile = file; - final TextRangeType finalTextRangeType = processingType; - - //todo show it if available options =) - - processor.setPostRunnable(new Runnable() { - @Override - public void run() { - if (document != null) { - int totalLinesProcessed = getProcessedLinesNumber(finalFile, charSeqBefore); - String info = prepareMessage(totalLinesProcessed, optimizeImports, rearrangeEntries, finalTextRangeType); - showHint(editor, info); - } - } - }); - - processor.run(); - } - - - private void showHint(@NotNull Editor editor, @NotNull String info) { - JComponent component = HintUtil.createInformationLabel(info); - LightweightHint hint = new LightweightHint(component); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, - HintManager.HIDE_BY_ANY_KEY| - HintManager.HIDE_BY_TEXT_CHANGE| - HintManager.HIDE_BY_SCROLLING, - 0, false); - } - - @NotNull - private String prepareMessage(int totalLinesProcessed, boolean optimizeImports, boolean rearrangeCode, @NotNull TextRangeType textRangeType) { - String linesInfo = ""; - if (totalLinesProcessed == 0) { - linesInfo = "No changes needed"; - } - else if (totalLinesProcessed > 0) { - linesInfo = "Changed " + totalLinesProcessed + " lines"; - } - - String scopeInfo = textRangeType == TextRangeType.VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null; - String actionsInfo = "Performed: formatting"; - if (optimizeImports) { - actionsInfo += ", import optimization"; - } - if (rearrangeCode) { - actionsInfo += " and code rearrangement"; - } - - String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText( - ActionManager.getInstance().getAction("ReformatFile")); - - String info = linesInfo; - if (scopeInfo != null) { - info += scopeInfo; - } - info += "\n"; - info += actionsInfo + "\n"; - info += shortcutInfo; - - return info; - } - - - private int getProcessedLinesNumber(final PsiFile file, final CharSequence before) { - Project project = file.getProject(); - Document document = PsiDocumentManager.getInstance(project).getDocument(file); - if (document == null) { - return 0; - } - - int totalLinesProcessed = 0; - try { - List ranges = FormatChangedTextUtil.calculateChangedTextRanges(project, file, before); - for (TextRange range : ranges) { - int lineStartNumber = document.getLineNumber(range.getStartOffset()); - int lineEndNumber = document.getLineNumber(range.getEndOffset()); - - int linesCoveredByRange = lineEndNumber - lineStartNumber + 1; - totalLinesProcessed += linesCoveredByRange; - } - } - catch (FilesTooBigForDiffException e) { - e.printStackTrace(); - } - return totalLinesProcessed; + new CodeProcessor(file, editor, currentRunOptions).processCode(); } @@ -530,12 +406,12 @@ public class ReformatCodeAction extends AnAction implements DumbAware { return true; } - public LayoutCodeOptions getLastRunReformatCodeOptions() { - if (ApplicationManager.getApplication().isUnitTestMode()) { - return myTestOptions; - } - return new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); - } + //public LayoutCodeOptions getLastRunReformatCodeOptions() { + // if (ApplicationManager.getApplication().isUnitTestMode()) { + // return myTestOptions; + // } + // return new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + //} } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java new file mode 100644 index 000000000000..c1b1e23ea05b --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java @@ -0,0 +1,56 @@ +/* + * 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.codeInsight.actions; + +public class ReformatCodeRunOptions implements LayoutCodeOptions { + + private boolean myRearrangeCode; + private boolean myOptimizeImports; + private TextRangeType myProcessingScope; + + public ReformatCodeRunOptions(TextRangeType processingScope) { + myProcessingScope = processingScope; + } + + public void setProcessingScope(TextRangeType processingScope) { + myProcessingScope = processingScope; + } + + @Override + public boolean isOptimizeImports() { + return myOptimizeImports; + } + + @Override + public boolean isRearrangeCode() { + return myRearrangeCode; + } + + public void setRearrangeCode(boolean rearrangeCode) { + myRearrangeCode = rearrangeCode; + } + + public void setOptimizeImports(boolean optimizeImports) { + myOptimizeImports = optimizeImports; + } + + @Override + public TextRangeType getTextRangeType() { + return myProcessingScope; + } + +} + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java index 7b17da453cd0..a7651cd34cb5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java @@ -43,9 +43,9 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO boolean canTargetVcsChanges = FormatChangedTextUtil.hasChanges(files, project); myOnlyChangedText.setEnabled(canTargetVcsChanges); - myOnlyChangedText.setSelected(canTargetVcsChanges && myLastRunSettings.getTextRangeType() == VCS_CHANGED_TEXT); - myOptimizeImports.setSelected(myLastRunSettings.isOptimizeImports()); - myRearrangeEntriesCb.setSelected(myLastRunSettings.isRearrangeCode()); + myOnlyChangedText.setSelected(canTargetVcsChanges && myLastRunSettings.getLastTextRangeType() == VCS_CHANGED_TEXT); + myOptimizeImports.setSelected(myLastRunSettings.getLastOptimizeImports()); + myRearrangeEntriesCb.setSelected(myLastRunSettings.getLastRearrangeCode()); setTitle(CodeInsightBundle.message("dialog.reformat.files.title")); init(); From 6d0b0f48858924f1cec4f7c5e37578c295f29b3f Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 15:10:28 +0200 Subject: [PATCH 008/231] refactored, reformat file is using CodeProcessor --- .../codeInsight/actions/CodeProcessor.java | 12 ++-- .../codeInsight/actions/LayoutCodeDialog.java | 60 ++++++++++++------- .../actions/ReformatCodeAction.java | 12 ++-- .../actions/ReformatFileAction.java | 18 +++--- 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index d6f17dc8f341..c0ce01968621 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -51,18 +51,18 @@ class CodeProcessor { public CodeProcessor(PsiFile file, Editor editor, - ReformatCodeRunOptions reformatCodeRunOptions) + LayoutCodeOptions runOptions) { myFile = file; myProject = file.getProject(); myEditor = editor; - myProcessingType = reformatCodeRunOptions.getTextRangeType(); + myProcessingType = runOptions.getTextRangeType(); - myShouldOptimizeImports = reformatCodeRunOptions.isOptimizeImports(); - myShouldRearrangeCode = reformatCodeRunOptions.isRearrangeCode(); - myProcessSelectedText = reformatCodeRunOptions.getTextRangeType() == SELECTED_TEXT; - myProcessChangesTextOnly = reformatCodeRunOptions.getTextRangeType() == VCS_CHANGED_TEXT; + myShouldOptimizeImports = runOptions.isOptimizeImports(); + myShouldRearrangeCode = runOptions.isRearrangeCode(); + myProcessSelectedText = runOptions.getTextRangeType() == SELECTED_TEXT; + myProcessChangesTextOnly = runOptions.getTextRangeType() == VCS_CHANGED_TEXT; myShouldNotify = editor != null && !myProcessSelectedText; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 36bbf8751a58..6dc2971b800c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; -public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions { +public class LayoutCodeDialog extends DialogWrapper { @NotNull private final Project myProject; @NotNull private final PsiFile myFile; @@ -52,6 +52,8 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions private JPanel myActionsPanel; private JPanel myScopePanel; + private LayoutCodeOptions myRunOptions; + public LayoutCodeDialog(@NotNull Project project, @NotNull PsiFile file, boolean textSelected, @@ -63,6 +65,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions myHelpId = helpId; myLastRunOptions = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); + myRunOptions = createOptionsBundledOnDialog(); setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text")); setTitle("Reformat File: " + file.getName()); @@ -77,16 +80,6 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions setUpTextRangeMode(); } - @Override - public TextRangeType getTextRangeType() { - if (myOnlyVCSChangedTextRb.isSelected()) { - return TextRangeType.VCS_CHANGED_TEXT; - } - if (mySelectedTextRadioButton.isSelected()) { - return TextRangeType.SELECTED_TEXT; - } - return TextRangeType.WHOLE_FILE; - } private void setUpTextRangeMode() { mySelectedTextRadioButton.setEnabled(myTextSelected); @@ -149,10 +142,10 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions private void saveCurrentConfiguration() { if (myOptimizeImportsCb.isEnabled()) { - myLastRunOptions.saveOptimizeImportsState(isOptimizeImports()); + myLastRunOptions.saveOptimizeImportsState(myRunOptions.isOptimizeImports()); } if (myRearrangeCodeCb.isEnabled()) { - myLastRunOptions.saveRearrangeState(myFile.getLanguage(), isRearrangeCode()); + myLastRunOptions.saveRearrangeState(myFile.getLanguage(), myRunOptions.isRearrangeCode()); } if (!mySelectedTextRadioButton.isSelected()) { @@ -160,6 +153,32 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions } } + @NotNull + private LayoutCodeOptions createOptionsBundledOnDialog() { + return new LayoutCodeOptions() { + @Override + public TextRangeType getTextRangeType() { + if (myOnlyVCSChangedTextRb.isSelected()) { + return TextRangeType.VCS_CHANGED_TEXT; + } + if (mySelectedTextRadioButton.isSelected()) { + return TextRangeType.SELECTED_TEXT; + } + return TextRangeType.WHOLE_FILE; + } + + @Override + public boolean isRearrangeCode() { + return myRearrangeCodeCb.isEnabled() && myRearrangeCodeCb.isSelected(); + } + + @Override + public boolean isOptimizeImports() { + return myOptimizeImportsCb.isEnabled() && myOptimizeImportsCb.isSelected(); + } + }; + } + @Nullable @Override protected JComponent createCenterPanel() { @@ -177,19 +196,14 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions HelpManager.getInstance().invokeHelp(myHelpId); } - @Override - public boolean isRearrangeCode() { - return myRearrangeCodeCb.isEnabled() && myRearrangeCodeCb.isSelected(); - } - - @Override - public boolean isOptimizeImports() { - return myOptimizeImportsCb.isEnabled() && myOptimizeImportsCb.isSelected(); - } - @Override protected void doOKAction() { super.doOKAction(); saveCurrentConfiguration(); } + + public LayoutCodeOptions getRunOptions() { + return myRunOptions; + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index 7b0422fd2475..dd9174c76f41 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -138,20 +138,20 @@ public class ReformatCodeAction extends AnAction implements DumbAware { LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); ReformatCodeRunOptions currentRunOptions = provider.getLastRunOptions(file); - TextRangeType processingType = currentRunOptions.getTextRangeType(); + TextRangeType processingScope = currentRunOptions.getTextRangeType(); if (hasSelection) { - processingType = TextRangeType.SELECTED_TEXT; + processingScope = TextRangeType.SELECTED_TEXT; } - else if (processingType == TextRangeType.VCS_CHANGED_TEXT) { + else if (processingScope == TextRangeType.VCS_CHANGED_TEXT) { if (isChangeNotTrackedForFile(project, file)) { - processingType = TextRangeType.WHOLE_FILE; + processingScope = TextRangeType.WHOLE_FILE; } } else { - processingType = TextRangeType.WHOLE_FILE; + processingScope = TextRangeType.WHOLE_FILE; } - currentRunOptions.setProcessingScope(processingType); + currentRunOptions.setProcessingScope(processingScope); new CodeProcessor(file, editor, currentRunOptions).processCode(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java index 5f1060ed01ff..aace3283c4b4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.actions; +import com.intellij.lang.LanguageFormatting; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.DumbAware; @@ -43,9 +44,9 @@ public class ReformatFileAction extends AnAction implements DumbAware { return; } - //todo if we can do something with it then - - presentation.setEnabled(true); + if (LanguageFormatting.INSTANCE.forContext(file) != null) { + presentation.setEnabled(true); + } } @Override @@ -69,13 +70,8 @@ public class ReformatFileAction extends AnAction implements DumbAware { LayoutCodeDialog dialog = new LayoutCodeDialog(project, file, hasSelection, HELP_ID); dialog.show(); - if (!dialog.isOK()) return; - - //new LayoutCodeProcessorBuilder(project, editor, file) - // .setReformatCode(dialog.isReformatCode()) - // .setOptimizeImports(dialog.isOptimizeImports()) - // .setRearrangeCode(dialog.isRearrangeCode()) - // .setTextRangeType(dialog.getTextRangeType()) - // .processCode(); + if (dialog.isOK()) { + new CodeProcessor(file, editor, dialog.getRunOptions()).processCode(); + } } } From 21f6646f1c77aad5a5567e897cb39fe3d9caf1a8 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 15:53:32 +0200 Subject: [PATCH 009/231] RearrangeCodeProcessor: extracted selected range calculation to superclass --- .../actions/AbstractLayoutCodeProcessor.java | 25 +++++++++++++++++++ .../actions/RearrangeCodeProcessor.java | 20 +++------------ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 3b4ed45f3c35..8e864a6b0423 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; @@ -35,6 +36,7 @@ import com.intellij.openapi.project.ProjectCoreUtil; import com.intellij.openapi.roots.GeneratedSourcesFilter; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ex.MessagesEx; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiBundle; import com.intellij.psi.PsiDirectory; @@ -43,11 +45,13 @@ import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SequentialModalProgressTask; import com.intellij.util.SequentialTask; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; @@ -572,4 +576,25 @@ public abstract class AbstractLayoutCodeProcessor { return true; } + + protected static Collection getSelectedRanges(@Nullable SelectionModel selectionModel) { + if (selectionModel == null) { + return ContainerUtil.emptyList(); + } + + final List ranges = new SmartList(); + if (selectionModel.hasSelection()) { + TextRange range = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); + ranges.add(range); + } + else if (selectionModel.hasBlockSelection()) { + int[] starts = selectionModel.getBlockSelectionStarts(); + int[] ends = selectionModel.getBlockSelectionEnds(); + for (int i = 0; i < starts.length; i++) { + ranges.add(TextRange.create(starts[i], ends[i])); + } + } + + return ranges; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index 4d765aa2ab9a..5519ec5e718f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -20,18 +20,16 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.arrangement.Rearranger; import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine; -import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; -import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @@ -84,19 +82,9 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { } public Collection getRangesToFormat(@NotNull PsiFile file) { - final List ranges = new SmartList(); - if (mySelectionModel != null && mySelectionModel.hasSelection()) { - ranges.add(TextRange.create(mySelectionModel.getSelectionStart(), mySelectionModel.getSelectionEnd())); - } - else if (mySelectionModel != null && mySelectionModel.hasBlockSelection()) { - int[] starts = mySelectionModel.getBlockSelectionStarts(); - int[] ends = mySelectionModel.getBlockSelectionEnds(); - for (int i = 0; i < starts.length; i++) { - ranges.add(TextRange.create(starts[i], ends[i])); - } - } - else { - ranges.add(TextRange.create(0, file.getTextLength())); + Collection ranges = getSelectedRanges(mySelectionModel); + if (ranges.isEmpty()) { + return ContainerUtil.newSmartList(file.getTextRange()); } return ranges; } From 9c3d2478d3ee6da7621fef9f945058335577a504 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 17:52:44 +0200 Subject: [PATCH 010/231] CodeProcessor: corrected LayoutCodeProcessors creation, minor simplifications and refactorings --- .../action/RearrangeCodeAction.java | 10 +++- .../actions/AbstractLayoutCodeProcessor.java | 21 ++++++-- .../codeInsight/actions/CodeProcessor.java | 29 ++++++----- .../actions/RearrangeCodeProcessor.java | 49 ++++++++++++------- .../actions/ReformatCodeProcessor.java | 31 ++++++++---- 5 files changed, 97 insertions(+), 43 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java index 843f8880d713..959bcf75e7d2 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/RearrangeCodeAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -61,6 +62,13 @@ public class RearrangeCodeAction extends AnAction { if (file == null) { return; } - new RearrangeCodeProcessor(project, file, editor.getSelectionModel()).run(); + + SelectionModel model = editor.getSelectionModel(); + if (model.hasSelection()) { + new RearrangeCodeProcessor(file, model).run(); + } + else { + new RearrangeCodeProcessor(file).run(); + } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 8e864a6b0423..b47970d4de18 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -18,6 +18,9 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.lang.LanguageFormatting; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; @@ -47,6 +50,7 @@ import com.intellij.util.SequentialModalProgressTask; import com.intellij.util.SequentialTask; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -577,11 +581,7 @@ public abstract class AbstractLayoutCodeProcessor { return true; } - protected static Collection getSelectedRanges(@Nullable SelectionModel selectionModel) { - if (selectionModel == null) { - return ContainerUtil.emptyList(); - } - + protected static Collection getSelectedRanges(@NotNull SelectionModel selectionModel) { final List ranges = new SmartList(); if (selectionModel.hasSelection()) { TextRange range = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); @@ -597,4 +597,15 @@ public abstract class AbstractLayoutCodeProcessor { return ranges; } + + protected void handleFileTooBigException(Logger logger, FilesTooBigForDiffException e, @NotNull PsiFile file) { + logger.info("Error while calculating changed ranges for: " + file.getVirtualFile(), e); + if (!ApplicationManager.getApplication().isUnitTestMode()) { + Notification notification = new Notification(ApplicationBundle.message("reformat.changed.text.file.too.big.notification.groupId"), + ApplicationBundle.message("reformat.changed.text.file.too.big.notification.title"), + ApplicationBundle.message("reformat.changed.text.file.too.big.notification.text", file.getName()), + NotificationType.INFORMATION); + notification.notify(file.getProject()); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index c0ce01968621..7ca3c93e5a67 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -21,7 +21,6 @@ import com.intellij.codeInsight.hint.HintUtil; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -61,25 +60,33 @@ class CodeProcessor { myShouldOptimizeImports = runOptions.isOptimizeImports(); myShouldRearrangeCode = runOptions.isRearrangeCode(); - myProcessSelectedText = runOptions.getTextRangeType() == SELECTED_TEXT; + myProcessSelectedText = myEditor != null && runOptions.getTextRangeType() == SELECTED_TEXT; myProcessChangesTextOnly = runOptions.getTextRangeType() == VCS_CHANGED_TEXT; - myShouldNotify = editor != null && !myProcessSelectedText; + myShouldNotify = myEditor != null && !myProcessSelectedText; } public void processCode() { - AbstractLayoutCodeProcessor processor; + AbstractLayoutCodeProcessor processor = null; if (myShouldOptimizeImports) { processor = new OptimizeImportsProcessor(myProject, myFile); - new ReformatCodeProcessor(processor, myProcessChangesTextOnly); + } + + if (processor != null) { + if (myProcessSelectedText) { + processor = new ReformatCodeProcessor(processor, myEditor.getSelectionModel()); + } + else { + processor = new ReformatCodeProcessor(processor, myProcessChangesTextOnly); + } } else { - SelectionModel model = myEditor.getSelectionModel(); - TextRange range = myProcessSelectedText && model.hasSelection() - ? new TextRange(model.getSelectionStart(), model.getSelectionEnd()) - : null; - - processor = new ReformatCodeProcessor(myProject, myFile, range, false); + if (myProcessSelectedText) { + processor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel()); + } + else { + processor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly); + } } if (myShouldRearrangeCode) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index 5519ec5e718f..3d949fe2a8b9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.actions; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; @@ -26,6 +27,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.arrangement.Rearranger; import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,7 +40,8 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public static final String COMMAND_NAME = "Rearrange code"; public static final String PROGRESS_TEXT = "Rearranging code..."; - @Nullable private SelectionModel mySelectionModel; + private static final Logger LOG = Logger.getInstance(RearrangeCodeProcessor.class); + private SelectionModel mySelectionModel; public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor) { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); @@ -49,13 +52,17 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { mySelectionModel = model; } - public RearrangeCodeProcessor(@NotNull Project project, - @NotNull PsiFile file, - @Nullable SelectionModel selectionModel) { - super(project, file, PROGRESS_TEXT, COMMAND_NAME, false); + public RearrangeCodeProcessor(@NotNull PsiFile file, + @NotNull SelectionModel selectionModel) + { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); mySelectionModel = selectionModel; } + public RearrangeCodeProcessor(@NotNull PsiFile file) { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); + } + public RearrangeCodeProcessor(@NotNull Project project, @NotNull PsiFile[] files, @NotNull String commandName, @@ -69,24 +76,32 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { return new FutureTask(new Callable() { @Override public Boolean call() throws Exception { - Collection ranges = processChangedTextOnly ? FormatChangedTextUtil.getChangedTextRanges(myProject, file) - : getRangesToFormat(file); - - RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges); - if (rearranger.couldRearrange()) { - rearranger.run(); + try { + Collection ranges = getRangesToFormat(file, processChangedTextOnly); + RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges); + if (rearranger.couldRearrange()) { + rearranger.run(); + } + return true; + } + catch (FilesTooBigForDiffException e) { + handleFileTooBigException(LOG, e, file); + return false; } - return true; } }); } - public Collection getRangesToFormat(@NotNull PsiFile file) { - Collection ranges = getSelectedRanges(mySelectionModel); - if (ranges.isEmpty()) { - return ContainerUtil.newSmartList(file.getTextRange()); + public Collection getRangesToFormat(@NotNull PsiFile file, boolean processChangedTextOnly) throws FilesTooBigForDiffException { + if (mySelectionModel != null) { + return getSelectedRanges(mySelectionModel); } - return ranges; + + if (processChangedTextOnly) { + return FormatChangedTextUtil.getChangedTextRanges(myProject, file); + } + + return ContainerUtil.newSmartList(file.getTextRange()); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 4ebe9274c1ca..c86255295a2a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -23,6 +23,7 @@ import com.intellij.notification.NotificationType; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -46,13 +47,24 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.ReformatCodeProcessor"); - private final Collection myRanges = new ArrayList(); private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.progress.common.text"); + private final Collection myRanges = new ArrayList(); + private SelectionModel mySelectionModel; public ReformatCodeProcessor(Project project, boolean processChangedTextOnly) { super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly); } + public ReformatCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { + super(file.getProject(), COMMAND_NAME, PROGRESS_TEXT, false); + mySelectionModel = selectionModel; + } + + public ReformatCodeProcessor(AbstractLayoutCodeProcessor processor, @NotNull SelectionModel selectionModel) { + super(processor, COMMAND_NAME, PROGRESS_TEXT); + mySelectionModel = selectionModel; + } + public ReformatCodeProcessor(AbstractLayoutCodeProcessor processor, boolean processChangedTextOnly) { super(processor, COMMAND_NAME, PROGRESS_TEXT); setProcessChangedTextOnly(processChangedTextOnly); @@ -73,6 +85,10 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } } + public ReformatCodeProcessor(@NotNull PsiFile file, boolean processChangedTextOnly) { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly); + } + public ReformatCodeProcessor(Project project, PsiFile[] files, @Nullable Runnable postRunnable, boolean processChangedTextOnly) { this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly); } @@ -101,14 +117,7 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get(); } catch (FilesTooBigForDiffException e) { - LOG.info("Error while calculating changed ranges for: " + file.getVirtualFile(), e); - if (!ApplicationManager.getApplication().isUnitTestMode()) { - Notification notification = new Notification(ApplicationBundle.message("reformat.changed.text.file.too.big.notification.groupId"), - ApplicationBundle.message("reformat.changed.text.file.too.big.notification.title"), - ApplicationBundle.message("reformat.changed.text.file.too.big.notification.text", file.getName()), - NotificationType.INFORMATION); - notification.notify(file.getProject()); - } + handleFileTooBigException(LOG, e, file); return false; } catch (IncorrectOperationException e) { @@ -124,6 +133,10 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { @NotNull private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException { + if (mySelectionModel != null) { + return getSelectedRanges(mySelectionModel); + } + if (processChangedTextOnly) { return FormatChangedTextUtil.getChangedTextRanges(myProject, file); } From 802b710a153d5163d5626d48a5ef448726a80392 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 18:04:33 +0200 Subject: [PATCH 011/231] CodeProcessor: changed ranges calculation needed for notification moved to pooled thread --- .../codeInsight/actions/CodeProcessor.java | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 7ca3c93e5a67..088f9d7c77be 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; @@ -99,23 +100,41 @@ class CodeProcessor { } if (myShouldNotify) { - final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myFile); - final CharSequence textBeforeChange = document != null ? document.getImmutableCharSequence() : null; - processor.setPostRunnable(new Runnable() { - @Override - public void run() { - if (document != null) { - String info = prepareMessage(document, textBeforeChange); - showHint(myEditor, info); - } - } - }); + Document document = PsiDocumentManager.getInstance(myProject).getDocument(myFile); + if (document != null) { + processor.setPostRunnable(getNotificationCallBack(document)); + } } processor.run(); } - private int getProcessedLinesNumber(final Document document, final CharSequence before) { + private Runnable getNotificationCallBack(@NotNull final Document document) { + final CharSequence textBeforeChange = document.getImmutableCharSequence(); + final Runnable calculateChangesAndNotify = new Runnable() { + @Override + public void run() { + final String info = prepareMessage(document, textBeforeChange); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (!myEditor.isDisposed() && myEditor.getComponent().isShowing()) { + showHint(myEditor, info); + } + } + }); + } + }; + + return new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().executeOnPooledThread(calculateChangesAndNotify); + } + }; + } + + private static int getProcessedLinesNumber(final Document document, final CharSequence before) { int totalLinesProcessed = 0; try { List ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before); @@ -163,7 +182,7 @@ class CodeProcessor { return info; } - private void showHint(@NotNull Editor editor, @NotNull String info) { + private static void showHint(@NotNull Editor editor, @NotNull String info) { JComponent component = HintUtil.createInformationLabel(info); LightweightHint hint = new LightweightHint(component); HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, From e2cc09d7a53948d43686b2f994dabe095126aba4 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 21:57:36 +0200 Subject: [PATCH 012/231] code processor: added tests on single file processing --- .../selectionReformat_after.java | 11 +++ .../selectionReformat_before.java | 11 +++ .../vcsChangedTextReformat_after.java | 19 +++++ .../vcsChangedTextReformat_before.java | 18 +++++ .../wholeFileReformat_after.java | 10 +++ .../wholeFileReformat_before.java | 10 +++ .../actions/MultiActionCodeProcessorTest.java | 81 +++++++++++++++++++ .../actions/ReformatCodeActionTest.java | 6 ++ .../actions/AbstractLayoutCodeProcessor.java | 2 +- .../actions/FormatChangedTextUtil.java | 12 ++- 10 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/actions/codeProcessor/selectionReformat_after.java create mode 100644 java/java-tests/testData/actions/codeProcessor/selectionReformat_before.java create mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java create mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java create mode 100644 java/java-tests/testData/actions/codeProcessor/wholeFileReformat_after.java create mode 100644 java/java-tests/testData/actions/codeProcessor/wholeFileReformat_before.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java diff --git a/java/java-tests/testData/actions/codeProcessor/selectionReformat_after.java b/java/java-tests/testData/actions/codeProcessor/selectionReformat_after.java new file mode 100644 index 000000000000..7e145c3004f0 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/selectionReformat_after.java @@ -0,0 +1,11 @@ +public class Test { + + int a = 2; + int b = 3; + + + public void run() { + int myFirst = 12; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/selectionReformat_before.java b/java/java-tests/testData/actions/codeProcessor/selectionReformat_before.java new file mode 100644 index 000000000000..d753fc6562c6 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/selectionReformat_before.java @@ -0,0 +1,11 @@ +public class Test { + + int a = 2; + int b = 3; + + + public void run() { + int myFirst = 12; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java new file mode 100644 index 000000000000..bf2d0b708392 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java @@ -0,0 +1,19 @@ +public class Test { + + int a = 3; + int b = 12; + +long t = 12; + + public void test() { + + int a = 3; + int b = 4; + } + + int rest = -12; + + public void run() { + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java new file mode 100644 index 000000000000..d837a92dbf22 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java @@ -0,0 +1,18 @@ +public class Test { + + int a = 3; + int b = 12; + +long t = 12; + + public void test() { + + int a = 3; + int b = 4; + } + + int rest = -12; + +public void run() {} + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_after.java b/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_after.java new file mode 100644 index 000000000000..05460c51a74b --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_after.java @@ -0,0 +1,10 @@ +public class Test { + + public int a = 3; + + + public void test() { + int c = 3; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_before.java b/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_before.java new file mode 100644 index 000000000000..e8d0ad4e5260 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_before.java @@ -0,0 +1,10 @@ +public class Test { + + public int a = 3; + + + public void test() { + int c = 3; + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java new file mode 100644 index 000000000000..b3ea6d35e421 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java @@ -0,0 +1,81 @@ +/* + * 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.codeInsight.actions; + +import com.intellij.JavaTestUtil; +import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.util.TextRange; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import java.util.List; + +public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtureTestCase { + + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath() + "/actions/codeProcessor/"; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + } + + @Override + public void tearDown() throws Exception { + myFixture.getFile().putUserData(FormatChangedTextUtil.CHANGED_RANGES, null); + super.tearDown(); + } + + public void doTest(LayoutCodeOptions options) { + myFixture.configureByFile(getTestDataPath() + getTestName(true) + "_before.java"); + CodeProcessor processor = new CodeProcessor(myFixture.getFile(), myFixture.getEditor(), options); + + if (options.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT) { + CaretModel model = myFixture.getEditor().getCaretModel(); + List ranges = ContainerUtil.mapNotNull(model.getAllCarets(), new Function() { + @Override + public TextRange fun(Caret caret) { + if (caret.hasSelection()) { + return new TextRange(caret.getSelectionStart(), caret.getSelectionEnd()); + } + return null; + } + }); + myFixture.getFile().putUserData(FormatChangedTextUtil.CHANGED_RANGES, ranges); + } + + processor.processCode(); + myFixture.checkResultByFile(getTestName(true) + "_after.java"); + } + + public void testSelectionReformat() { + doTest(new ReformatCodeRunOptions(TextRangeType.SELECTED_TEXT)); + } + + public void testWholeFileReformat() { + doTest(new ReformatCodeRunOptions(TextRangeType.WHOLE_FILE)); + } + + public void testVcsChangedTextReformat() { + doTest(new ReformatCodeRunOptions(TextRangeType.VCS_CHANGED_TEXT)); + } + + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index 20b483c9b077..b43059389253 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -85,4 +85,10 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkFormationAndImportsOptimizationFor(files); } + + + + + + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index b47970d4de18..37ad0423e6a8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -581,7 +581,7 @@ public abstract class AbstractLayoutCodeProcessor { return true; } - protected static Collection getSelectedRanges(@NotNull SelectionModel selectionModel) { + protected static List getSelectedRanges(@NotNull SelectionModel selectionModel) { final List ranges = new SmartList(); if (selectionModel.hasSelection()) { TextRange range = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index b3dfef2bcb2a..3aee7c9f9d21 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.actions; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.Result; import com.intellij.openapi.diagnostic.Logger; @@ -27,6 +28,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; @@ -53,7 +55,8 @@ import java.util.*; public class FormatChangedTextUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil"); - + protected static final Key> CHANGED_RANGES = Key.create("changed.ranges.since.last.revision"); + private FormatChangedTextUtil() { } @@ -229,6 +232,13 @@ public class FormatChangedTextUtil { @NotNull public static List getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) throws FilesTooBigForDiffException { + if (ApplicationManager.getApplication().isUnitTestMode()) { + List testData = file.getUserData(CHANGED_RANGES); + if (testData != null) { + return testData; + } + } + Document document = PsiDocumentManager.getInstance(project).getDocument(file); if (document == null) return ContainerUtil.emptyList(); From c96d467d5b6f713401a9b8ba96d98319bcfc7a9a Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 25 Dec 2014 23:06:30 +0200 Subject: [PATCH 013/231] code processor: added tests on single file reformat and import optimization --- .../selectedTextAndOptimizeImports_after.java | 14 ++++++++++++ ...selectedTextAndOptimizeImports_before.java | 17 ++++++++++++++ ...sChangedTextReformatAndOptimize_after.java | 18 +++++++++++++++ ...ChangedTextReformatAndOptimize_before.java | 22 +++++++++++++++++++ .../wholeFileReformatAndOptimize_after.java | 11 ++++++++++ .../wholeFileReformatAndOptimize_before.java | 14 ++++++++++++ .../actions/MultiActionCodeProcessorTest.java | 20 +++++++++++++---- .../actions/ReformatCodeRunOptions.java | 6 +++-- 8 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_after.java create mode 100644 java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_before.java create mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java create mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java create mode 100644 java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_after.java create mode 100644 java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_before.java diff --git a/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_after.java b/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_after.java new file mode 100644 index 000000000000..edb36d680a69 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_after.java @@ -0,0 +1,14 @@ +import java.util.ArrayList; +import java.util.List; + + +public class Test { + + public static void main(String[] args) { + List list = new ArrayList(); + int a = 3; + +int b = 3; + } + +} diff --git a/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_before.java b/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_before.java new file mode 100644 index 000000000000..2256d473f765 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_before.java @@ -0,0 +1,17 @@ +import java.lang.String; +import java.util.List; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.HashSet; + + +public class Test { + + public static void main(String[] args) { +List list = new ArrayList(); +int a = 3; + +int b = 3; + } + +} diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java new file mode 100644 index 000000000000..122700a59862 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java @@ -0,0 +1,18 @@ +import java.util.ArrayList; +import java.util.List; + + +public class Test { + + public static void main(String[] args) { + List list = new ArrayList(); + int a = 3; + +int b = 3; + } + + + public void test() { + } + +} diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java new file mode 100644 index 000000000000..878031804ea0 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java @@ -0,0 +1,22 @@ +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.HashSet; + + +public class Test { + + public static void main(String[] args) { + List list = new ArrayList(); +int a = 3; + +int b = 3; + } + + + +public void test() { +} + +} diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_after.java b/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_after.java new file mode 100644 index 000000000000..b3c340724e6b --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_after.java @@ -0,0 +1,11 @@ +import java.util.ArrayList; +import java.util.List; + + +public class Test { + + public static void main(String[] args) { + List list = new ArrayList(); + } + +} diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_before.java b/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_before.java new file mode 100644 index 000000000000..a996d55202f7 --- /dev/null +++ b/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_before.java @@ -0,0 +1,14 @@ +import java.lang.String; +import java.util.List; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.HashSet; + + +public class Test { + + public static void main(String[] args) { +List list = new ArrayList(); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java index b3ea6d35e421..f457bf794fee 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java @@ -25,6 +25,8 @@ import com.intellij.util.containers.ContainerUtil; import java.util.List; +import static com.intellij.codeInsight.actions.TextRangeType.*; + public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtureTestCase { @Override @@ -47,7 +49,7 @@ public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtur myFixture.configureByFile(getTestDataPath() + getTestName(true) + "_before.java"); CodeProcessor processor = new CodeProcessor(myFixture.getFile(), myFixture.getEditor(), options); - if (options.getTextRangeType() == TextRangeType.VCS_CHANGED_TEXT) { + if (options.getTextRangeType() == VCS_CHANGED_TEXT) { CaretModel model = myFixture.getEditor().getCaretModel(); List ranges = ContainerUtil.mapNotNull(model.getAllCarets(), new Function() { @Override @@ -66,16 +68,26 @@ public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtur } public void testSelectionReformat() { - doTest(new ReformatCodeRunOptions(TextRangeType.SELECTED_TEXT)); + doTest(new ReformatCodeRunOptions(SELECTED_TEXT)); } public void testWholeFileReformat() { - doTest(new ReformatCodeRunOptions(TextRangeType.WHOLE_FILE)); + doTest(new ReformatCodeRunOptions(WHOLE_FILE)); } public void testVcsChangedTextReformat() { - doTest(new ReformatCodeRunOptions(TextRangeType.VCS_CHANGED_TEXT)); + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT)); } + public void testWholeFileReformatAndOptimize() { + doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true)); + } + public void testSelectedTextAndOptimizeImports() { + doTest(new ReformatCodeRunOptions(SELECTED_TEXT).setOptimizeImports(true)); + } + + //public void testVcsChangedTextReformatAndOptimize() { + // doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true)); + //} } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java index c1b1e23ea05b..67d20e28b735 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeRunOptions.java @@ -39,12 +39,14 @@ public class ReformatCodeRunOptions implements LayoutCodeOptions { return myRearrangeCode; } - public void setRearrangeCode(boolean rearrangeCode) { + public ReformatCodeRunOptions setRearrangeCode(boolean rearrangeCode) { myRearrangeCode = rearrangeCode; + return this; } - public void setOptimizeImports(boolean optimizeImports) { + public ReformatCodeRunOptions setOptimizeImports(boolean optimizeImports) { myOptimizeImports = optimizeImports; + return this; } @Override From 023536cba45ec4a059d8500ede742506a596ec97 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Sun, 11 Jan 2015 19:46:54 +0300 Subject: [PATCH 014/231] Rename TaskRepository#getPossibleTaskStates to getAvailableTaskStates --- .../src/com/intellij/tasks/TaskRepository.java | 16 +++++++++------- .../com/intellij/tasks/TaskRepositoryType.java | 2 +- .../com/intellij/tasks/jira/JiraRemoteApi.java | 2 +- .../com/intellij/tasks/jira/JiraRepository.java | 4 ++-- .../tasks/jira/rest/api2/JiraRestApi2.java | 2 +- .../rest/api20alpha1/JiraRestApi20Alpha1.java | 2 +- .../intellij/tasks/jira/soap/JiraLegacyApi.java | 2 +- .../intellij/tasks/actions/OpenTaskDialog.java | 2 +- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 535ba131f985..1e745aed291d 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -18,6 +18,8 @@ package com.intellij.tasks; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.impl.CancellableRunnable; +import com.intellij.tasks.impl.BaseRepository; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; import com.intellij.util.xmlb.annotations.Transient; @@ -35,7 +37,7 @@ import java.util.concurrent.Callable; * * @author Dmitry Avdeev * @see TaskRepositoryType - * @see com.intellij.tasks.impl.BaseRepository + * @see BaseRepository */ @Tag("server") public abstract class TaskRepository { @@ -110,7 +112,7 @@ public abstract class TaskRepository { /** * Returns an object that can test connection. - * {@link com.intellij.openapi.vcs.impl.CancellableRunnable#cancel()} should cancel the process. + * {@link CancellableRunnable#cancel()} should cancel the process. * * @return null if not supported */ @@ -171,7 +173,7 @@ public abstract class TaskRepository { * @return set of available states */ @NotNull - public Set getPossibleStates(@NotNull Task task) throws Exception { + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { //noinspection unchecked return getRepositoryType().getPossibleTaskStates(); } @@ -201,15 +203,15 @@ public abstract class TaskRepository { } /** - * Update state of the task on server. It's guaranteed that only issues returned by {@link #getPossibleStates(Task)} + * Update state of the task on server. It's guaranteed that only issues returned by {@link #getAvailableTaskStates(Task)} * will be passed here. *

- * Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and supported states in {@link #getPossibleStates(Task)}. + * Don't forget to add {@link #STATE_UPDATING} in {@link #getFeatures()} and supported states in {@link #getAvailableTaskStates(Task)}. * * @param task issue to update * @param state new state of the issue - * @see com.intellij.tasks.TaskRepositoryType#getPossibleTaskStates() - * @see com.intellij.tasks.TaskRepository#getFeatures() + * @see TaskRepositoryType#getPossibleTaskStates() + * @see TaskRepository#getFeatures() */ public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { setTaskState(task, ((TaskState)state)); diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java index fac6ad863524..d4575cf3eb92 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepositoryType.java @@ -68,7 +68,7 @@ public abstract class TaskRepositoryType implements Ta /** * @return states that can be set by {@link TaskRepository#setTaskState(Task, CustomTaskState)} - * @deprecated Use {@link com.intellij.tasks.TaskRepository#getPossibleStates(Task)} instead. + * @deprecated Use {@link TaskRepository#getAvailableTaskStates(Task)} instead. */ @Deprecated public EnumSet getPossibleTaskStates() { diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java index 11efe39cc3de..7b760769a0e3 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRemoteApi.java @@ -31,7 +31,7 @@ public abstract class JiraRemoteApi { public abstract Task findTask(@NotNull String key) throws Exception; @NotNull - public abstract Set getPossibleStates(@NotNull Task task) throws Exception; + public abstract Set getAvailableTaskStates(@NotNull Task task) throws Exception; public abstract void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception; diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java index cea2c21a4e75..ec0e612f4e81 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java @@ -355,8 +355,8 @@ public class JiraRepository extends BaseRepositoryImpl { @NotNull @Override - public Set getPossibleStates(@NotNull Task task) throws Exception { - return myApiVersion.getPossibleStates(task); + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + return myApiVersion.getAvailableTaskStates(task); } public void setSearchQuery(String searchQuery) { diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java index 72cdc8130960..8163b1cca166 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java @@ -83,7 +83,7 @@ public class JiraRestApi2 extends JiraRestApi { @NotNull @Override - public Set getPossibleStates(@NotNull Task task) throws Exception { + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { final GetMethod method = new GetMethod(myRepository.getRestUrl("issue", task.getId(), "transitions")); method.setQueryString("expand=transitions.fields"); final String response = myRepository.executeMethod(method); diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java index a87f6052d93b..aa95f0b432a6 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java @@ -34,7 +34,7 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { @NotNull @Override - public Set getPossibleStates(@NotNull Task task) throws Exception { + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { final HashSet result = new HashSet(); result.add(TaskState.IN_PROGRESS); result.add(TaskState.RESOLVED); diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java index 857c6e11aa5e..7f5ab27cc9a1 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/soap/JiraLegacyApi.java @@ -106,7 +106,7 @@ public class JiraLegacyApi extends JiraRemoteApi { @NotNull @Override - public Set getPossibleStates(@NotNull Task task) throws Exception { + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { return Collections.emptySet(); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index b1008d493f63..1e19e7d73fd0 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -119,7 +119,7 @@ public class OpenTaskDialog extends DialogWrapper { @NotNull @Override protected Set fetch(@NotNull ProgressIndicator indicator) throws Exception { - return repository.getPossibleStates(myTask); + return repository.getAvailableTaskStates(myTask); } @Nullable From a1e8c465b828e68681a557bdb39278b0ebcfa3cc Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Sun, 11 Jan 2015 19:47:48 +0300 Subject: [PATCH 015/231] Add SimpleTaskState class, use it instead of JiraCustomTaskState --- .../intellij/tasks/impl/SimpleTaskState.java | 49 +++++++++++++++++++ .../tasks/jira/rest/api2/JiraRestApi2.java | 14 +++--- .../model/JiraTransitionsWrapperApi2.java | 6 +-- .../jira/rest/model/JiraCustomTaskState.java | 37 -------------- 4 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java delete mode 100644 plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java new file mode 100644 index 000000000000..8aefd3986769 --- /dev/null +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java @@ -0,0 +1,49 @@ +package com.intellij.tasks.impl; + +import com.intellij.tasks.CustomTaskState; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class SimpleTaskState implements CustomTaskState { + private final String myId; + private final String myPresentableName; + + public SimpleTaskState(@NotNull String id, @NotNull String presentableName) { + myId = id; + myPresentableName = presentableName; + } + + @NotNull + @Override + public String getId() { + return myId; + } + + @NotNull + @Override + public String getPresentableName() { + return myPresentableName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SimpleTaskState)) return false; + + final SimpleTaskState state = (SimpleTaskState)o; + + if (!myId.equals(state.myId)) return false; + if (!myPresentableName.equals(state.myPresentableName)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myId.hashCode(); + result = 31 * result + myPresentableName.hashCode(); + return result; + } +} diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java index 8163b1cca166..b83607481fac 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/JiraRestApi2.java @@ -10,7 +10,6 @@ import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.rest.JiraRestApi; import com.intellij.tasks.jira.rest.api2.model.JiraIssueApi2; import com.intellij.tasks.jira.rest.api2.model.JiraTransitionsWrapperApi2; -import com.intellij.tasks.jira.rest.model.JiraCustomTaskState; import com.intellij.tasks.jira.rest.model.JiraIssue; import com.intellij.tasks.jira.rest.model.JiraResponseWrapper; import org.apache.commons.httpclient.methods.GetMethod; @@ -70,14 +69,17 @@ public class JiraRestApi2 extends JiraRestApi { @NotNull @Override protected String getRequestForStateTransition(@NotNull CustomTaskState state) { - final JiraCustomTaskState transition = (JiraCustomTaskState)state; assert StringUtil.isNotEmpty(state.getId()); - final String resolutionName = transition.getResolutionName(); - if (resolutionName != null) { - return "{\"transition\": {\"id\": \"" + state.getId() + "\"}, \"fields\": {\"resolution\": {\"name\": \"" + resolutionName + "\"}}}"; + final String stateId = state.getId(); + final int index = stateId.indexOf(':'); + if (index >= 0) { + return "{" + + " \"transition\": {\"id\": \"" + stateId.substring(0, index) + "\"}, " + + " \"fields\": {\"resolution\": {\"name\": \"" + stateId.substring(index + 1) + "\"}}" + + "}"; } else { - return "{\"transition\": {\"id\": \"" + state.getId() + "\"}}"; + return "{\"transition\": {\"id\": \"" + stateId + "\"}}"; } } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java index 3c1df68b4d35..48dd231c9dea 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java @@ -4,7 +4,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; import com.intellij.tasks.CustomTaskState; -import com.intellij.tasks.jira.rest.model.JiraCustomTaskState; +import com.intellij.tasks.impl.SimpleTaskState; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -42,14 +42,14 @@ public class JiraTransitionsWrapperApi2 { if (fieldName.equals("resolution") && fieldInfo.get("required").getAsBoolean()) { for (JsonElement allowedValue : fieldInfo.getAsJsonArray("allowedValues")) { final String resolutionName = allowedValue.getAsJsonObject().get("name").getAsString(); - result.add(new JiraCustomTaskState(transitionName + " (" + resolutionName + ")", transitionId, resolutionName)); + result.add(new SimpleTaskState(transitionName + " (" + resolutionName + ")", transitionId + resolutionName)); } break; } } } if (fieldName == null) { - result.add(new JiraCustomTaskState(transitionName, transitionId, null)); + result.add(new SimpleTaskState(transitionName, String.valueOf(transitionId))); } } return result; diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java deleted file mode 100644 index 96fafeb5fa66..000000000000 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/model/JiraCustomTaskState.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.intellij.tasks.jira.rest.model; - -import com.intellij.tasks.CustomTaskState; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author Mikhail Golubev - */ -public class JiraCustomTaskState implements CustomTaskState { - private final int myTransitionId; - private final String myPresentableName; - private final String myResolutionId; - - public JiraCustomTaskState(@NotNull String presentableName, int transitionId, @Nullable String resolutionName) { - myTransitionId = transitionId; - myPresentableName = presentableName; - myResolutionId = resolutionName; - } - - @Nullable - public String getResolutionName() { - return myResolutionId; - } - - @NotNull - @Override - public String getId() { - return String.valueOf(myTransitionId); - } - - @NotNull - @Override - public String getPresentableName() { - return myPresentableName; - } -} From 4037f034b08ef7900cb2897af23ecaa99b50ac14 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 12 Jan 2015 00:27:55 +0300 Subject: [PATCH 016/231] TaskRepository remembers last state used when opening task --- .../com/intellij/tasks/CustomTaskState.java | 80 ++++++++++++++++++- .../com/intellij/tasks/TaskRepository.java | 32 +++++++- .../src/com/intellij/tasks/TaskState.java | 17 ++-- .../intellij/tasks/impl/BaseRepository.java | 13 +++ .../intellij/tasks/impl/SimpleTaskState.java | 49 ------------ .../model/JiraTransitionsWrapperApi2.java | 35 +++++--- .../rest/api20alpha1/JiraRestApi20Alpha1.java | 30 ++++--- .../tasks/actions/OpenTaskDialog.java | 29 +++---- .../com/intellij/tasks/impl/TaskUiUtil.java | 16 +++- .../tasks/trello/TrelloRepositoryEditor.java | 10 +++ 10 files changed, 201 insertions(+), 110 deletions(-) delete mode 100644 plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java index 2f8cf8de2c64..dbae96362d79 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java @@ -1,14 +1,86 @@ package com.intellij.tasks; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Mikhail Golubev */ -public interface CustomTaskState { - @NotNull - String getId(); +public class CustomTaskState { + private String myId; + private String myPresentableName; + private boolean myPredefined; + + /** + * For serialization purposes only. + */ + public CustomTaskState() { + } + + public CustomTaskState(@NotNull String id, @NotNull String name) { + myId = id; + myPresentableName = name; + } @NotNull - String getPresentableName(); + public String getId() { + return myId; + } + + /** + * For serialization purposes only. + */ + public void setId(String id) { + myId = id; + } + + @NotNull + public String getPresentableName() { + return myPresentableName; + } + + /** + * For serialization purposes only. + */ + public void setPresentableName(@NotNull String name) { + myPresentableName = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CustomTaskState)) return false; + + final CustomTaskState state = (CustomTaskState)o; + + return myId.equals(state.myId); + } + + @Override + public int hashCode() { + return myId.hashCode(); + } + + @Nullable + public TaskState asPredefinedTaskState() { + if (isPredefined()) { + try { + return TaskState.valueOf(getId()); + } + catch (IllegalArgumentException ignored) { + } + } + return null; + } + + private boolean isPredefined() { + return myPredefined; + } + + /** + * For serialization purposes only. + */ + public void setPredefined(boolean predefined) { + myPredefined = predefined; + } } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 1e745aed291d..93c2f2dbf6ab 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -20,6 +20,8 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.impl.CancellableRunnable; import com.intellij.tasks.impl.BaseRepository; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; import com.intellij.util.xmlb.annotations.Transient; @@ -175,9 +177,27 @@ public abstract class TaskRepository { @NotNull public Set getAvailableTaskStates(@NotNull Task task) throws Exception { //noinspection unchecked - return getRepositoryType().getPossibleTaskStates(); + return ContainerUtil.map2Set(getRepositoryType().getPossibleTaskStates(), new Function() { + @Override + public CustomTaskState fun(TaskState state) { + return state.asCustomTaskState(); + } + }); } + /** + * Remember state used for opening of task. + * @param state preferred task state + */ + public abstract void setPreferredOpenTaskState(@Nullable CustomTaskState state); + + /** + * Task state used last time for opening task. + * @return preferred task state + */ + @Nullable + public abstract CustomTaskState getPreferredOpenTaskState(); + /** * @param id task ID. Don't forget to define {@link #extractId(String)}, if your server uses not PROJECT-123 format for task IDs. * @return found task or {@code null} otherwise. Basically you should return {@code null} on e.g. 404 error and throw exception with @@ -214,7 +234,15 @@ public abstract class TaskRepository { * @see TaskRepository#getFeatures() */ public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { - setTaskState(task, ((TaskState)state)); + TaskState predefinedState = null; + try { + predefinedState = TaskState.valueOf(state.getId()); + } + catch (IllegalArgumentException ignored) { + } + if (predefinedState != null) { + setTaskState(task, predefinedState); + } } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java index 27b8fb87c473..95691db49270 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java @@ -18,9 +18,11 @@ package com.intellij.tasks; import org.jetbrains.annotations.NotNull; /** + * Predefined common task states used before {@link CustomTaskState} was introduced. + * * @author Dmitry Avdeev */ -public enum TaskState implements CustomTaskState { +public enum TaskState { SUBMITTED("Submitted"), OPEN("Open"), IN_PROGRESS("In Progress"), @@ -36,14 +38,9 @@ public enum TaskState implements CustomTaskState { } @NotNull - @Override - public String getId() { - return ""; - } - - @NotNull - @Override - public String getPresentableName() { - return myPresentableName; + public CustomTaskState asCustomTaskState() { + final CustomTaskState result = new CustomTaskState(name(), myPresentableName); + result.setPredefined(true); + return result; } } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java index 8423736c8c10..49ad62e2d1aa 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java @@ -18,6 +18,7 @@ package com.intellij.tasks.impl; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.PasswordUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.TaskRepository; import com.intellij.tasks.TaskRepositoryType; import com.intellij.util.xmlb.annotations.Tag; @@ -40,6 +41,7 @@ public abstract class BaseRepository extends TaskRepository { protected boolean myUseProxy; protected boolean myUseHttpAuthentication; protected boolean myLoginAnonymously; + protected CustomTaskState myPreferredOpenTaskState; public BaseRepository(TaskRepositoryType type) { super(type); @@ -135,6 +137,17 @@ public abstract class BaseRepository extends TaskRepository { myLoginAnonymously = loginAnonymously; } + @Override + public void setPreferredOpenTaskState(@Nullable CustomTaskState state) { + myPreferredOpenTaskState = state; + } + + @Nullable + @Override + public CustomTaskState getPreferredOpenTaskState() { + return myPreferredOpenTaskState; + } + @Nullable public String extractId(@NotNull String taskName) { Matcher matcher = PATTERN.matcher(taskName); diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java deleted file mode 100644 index 8aefd3986769..000000000000 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/SimpleTaskState.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.intellij.tasks.impl; - -import com.intellij.tasks.CustomTaskState; -import org.jetbrains.annotations.NotNull; - -/** - * @author Mikhail Golubev - */ -public class SimpleTaskState implements CustomTaskState { - private final String myId; - private final String myPresentableName; - - public SimpleTaskState(@NotNull String id, @NotNull String presentableName) { - myId = id; - myPresentableName = presentableName; - } - - @NotNull - @Override - public String getId() { - return myId; - } - - @NotNull - @Override - public String getPresentableName() { - return myPresentableName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof SimpleTaskState)) return false; - - final SimpleTaskState state = (SimpleTaskState)o; - - if (!myId.equals(state.myId)) return false; - if (!myPresentableName.equals(state.myPresentableName)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = myId.hashCode(); - result = 31 * result + myPresentableName.hashCode(); - return result; - } -} diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java index 48dd231c9dea..a1534ab81e8a 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api2/model/JiraTransitionsWrapperApi2.java @@ -3,8 +3,8 @@ package com.intellij.tasks.jira.rest.api2.model; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.tasks.CustomTaskState; -import com.intellij.tasks.impl.SimpleTaskState; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -12,7 +12,9 @@ import java.util.*; /** * @author Mikhail Golubev */ +@SuppressWarnings({"unused", "FieldMayBeFinal"}) public class JiraTransitionsWrapperApi2 { + private static final Logger LOG = Logger.getInstance(JiraTransitionsWrapperApi2.class); private List transitions = Collections.emptyList(); static class JiraTransition { @@ -31,25 +33,34 @@ public class JiraTransitionsWrapperApi2 { @NotNull public Set getTransitions() { final Set result = new LinkedHashSet(); + nextTransition: for (JiraTransition transition : transitions) { - final int transitionId = transition.id; - final String transitionName = transition.target.name; - String fieldName = null; + final String stateName = transition.target.name; + final List resolutions = new ArrayList(); if (transition.fields != null) { for (Map.Entry field : transition.fields.entrySet()) { - fieldName = field.getKey(); + final String fieldName = field.getKey(); final JsonObject fieldInfo = field.getValue().getAsJsonObject(); - if (fieldName.equals("resolution") && fieldInfo.get("required").getAsBoolean()) { - for (JsonElement allowedValue : fieldInfo.getAsJsonArray("allowedValues")) { - final String resolutionName = allowedValue.getAsJsonObject().get("name").getAsString(); - result.add(new SimpleTaskState(transitionName + " (" + resolutionName + ")", transitionId + resolutionName)); + if (fieldInfo.get("required").getAsBoolean()) { + if (fieldName.equals("resolution")) { + for (JsonElement allowedValue : fieldInfo.getAsJsonArray("allowedValues")) { + resolutions.add(allowedValue.getAsJsonObject().get("name").getAsString()); + } + } + else { + LOG.info("Unknown required field '" + fieldName + "' for transition '" + stateName + "'"); + continue nextTransition; } - break; } } } - if (fieldName == null) { - result.add(new SimpleTaskState(transitionName, String.valueOf(transitionId))); + if (resolutions.isEmpty()) { + result.add(new CustomTaskState(String.valueOf(transition.id), stateName)); + } + else { + for (String resolution : resolutions) { + result.add(new CustomTaskState(transition.id + ":" + resolution, stateName + " (" + resolution + ")")); + } } } return result; diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java index aa95f0b432a6..0108ef688f80 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java @@ -36,9 +36,9 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { @Override public Set getAvailableTaskStates(@NotNull Task task) throws Exception { final HashSet result = new HashSet(); - result.add(TaskState.IN_PROGRESS); - result.add(TaskState.RESOLVED); - result.add(TaskState.REOPENED); + result.add(TaskState.IN_PROGRESS.asCustomTaskState()); + result.add(TaskState.RESOLVED.asCustomTaskState()); + result.add(TaskState.REOPENED.asCustomTaskState()); return result; } @@ -72,17 +72,21 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { protected String getRequestForStateTransition(@NotNull CustomTaskState state) { // REST API of JIRA 4.x for retrieving possible transitions is very limited: we can't fetch possible resolutions and // names of transition destinations. So we have no other options than to hardcode them. - switch ((TaskState)state) { - case IN_PROGRESS: - return "{\"transition\": \"4\"}"; - case RESOLVED: - // 5 for "Resolved", 2 for "Closed" - return "{\"transition\": \"5\", \"resolution\": \"Fixed\"}"; - case REOPENED: - return "{\"transition\": \"3\"}"; - default: - return null; + final TaskState taskState = state.asPredefinedTaskState(); + if (taskState != null) { + switch (taskState) { + case IN_PROGRESS: + return "{\"transition\": \"4\"}"; + case RESOLVED: + // 5 for "Resolved", 2 for "Closed" + return "{\"transition\": \"5\", \"resolution\": \"Fixed\"}"; + case REOPENED: + return "{\"transition\": \"3\"}"; + default: + return null; + } } + return null; } @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 1e19e7d73fd0..0efa5396b424 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -54,19 +54,7 @@ public class OpenTaskDialog extends DialogWrapper { private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.actions.SimpleOpenTaskDialog"); public static final String START_FROM_BRANCH = "start.from.branch"; - private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState() { - @NotNull - @Override - public String getId() { - return ""; - } - - @NotNull - @Override - public String getPresentableName() { - return "-- do not update --"; - } - }; + private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); private JPanel myPanel; @BindControl(value = "clearContext", instant = true) @@ -122,6 +110,12 @@ public class OpenTaskDialog extends DialogWrapper { return repository.getAvailableTaskStates(myTask); } + @Nullable + @Override + public CustomTaskState getSelectedItem() { + return repository.getPreferredOpenTaskState(); + } + @Nullable @Override public CustomTaskState getExtraItem() { @@ -232,11 +226,12 @@ public class OpenTaskDialog extends DialogWrapper { taskManager.getState().createChangelist = myCreateChangelist.isSelected(); taskManager.getState().createBranch = myCreateBranch.isSelected(); - TaskRepository repository = myTask.getRepository(); - final CustomTaskState selectedItem = (CustomTaskState)myStateComboBox.getSelectedItem(); - if (repository != null && selectedItem != null && selectedItem != DO_NOT_UPDATE_STATE) { + final TaskRepository repository = myTask.getRepository(); + final CustomTaskState taskState = (CustomTaskState)myStateComboBox.getSelectedItem(); + if (repository != null && taskState != null && taskState != DO_NOT_UPDATE_STATE) { try { - repository.setTaskState(myTask, selectedItem); + repository.setTaskState(myTask, taskState); + repository.setPreferredOpenTaskState(taskState); } catch (Exception ex) { Messages.showErrorDialog(myProject, ex.getMessage(), "Cannot Set State For Issue"); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java index 38d7fe7f6c03..5bffedf3e903 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java @@ -7,6 +7,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; +import com.intellij.tasks.config.TaskRepositoryEditor; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; @@ -60,7 +61,7 @@ public class TaskUiUtil { /** * {@link #onSuccess()} can't be used for this purpose, because it doesn't consider current modality state - * which will prevent UI updating in modal dialog (e.g. in {@link com.intellij.tasks.config.TaskRepositoryEditor}). + * which will prevent UI updating in modal dialog (e.g. in {@link TaskRepositoryEditor}). */ @Nullable @Override @@ -104,14 +105,23 @@ public class TaskUiUtil { /** * Return item to select after every combo box update. Default implementation select item, returned by {@link #getExtraItem()}. + * If returned value is not present in the list it will be added depending on policy set by {@link #addSelectedItemIfMissing()}. * * @return selected combo box item + * @see #addSelectedItemIfMissing() */ @Nullable public T getSelectedItem() { return getExtraItem(); } + /** + * @return whether value returned by {@link #getSelectedItem()} should be forcibly added to the combo box. + */ + protected boolean addSelectedItemIfMissing() { + return false; + } + @SuppressWarnings("unchecked") @Override protected void updateUI() { @@ -127,7 +137,7 @@ public class TaskUiUtil { final T selected = getSelectedItem(); if (selected != null) { - if (!selected.equals(extra) && !myResult.contains(selected)) { + if (!selected.equals(extra) && !myResult.contains(selected) && addSelectedItemIfMissing()) { myComboBox.addItem(selected); } myComboBox.setSelectedItem(selected); @@ -147,7 +157,7 @@ public class TaskUiUtil { } /** - * Very simple wrapper around {@link com.intellij.ui.ListCellRendererWrapper} useful for + * Very simple wrapper around {@link ListCellRendererWrapper} useful for * combo boxes where each item has plain text representation with special message for * {@code null} value. */ diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java index 0ea5905cbcb2..f7dcd54d3baa 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java @@ -260,6 +260,11 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor { @@ -284,5 +289,10 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor Date: Mon, 12 Jan 2015 13:19:27 +0300 Subject: [PATCH 017/231] Field 'markAsInProgress' in configuration of TaskManager is no longer needed --- .../tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 11c09894b852..94f940af9c5a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -1036,7 +1036,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe public boolean saveContextOnCommit = true; public boolean trackContextForNewChangelist = false; - public boolean markAsInProgress = false; public String changelistNameFormat = "{id} {summary}"; public String branchNameFormat = "{id}"; From 2bd87412882e9da83836fde5776d6bd611633fab Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 12 Jan 2015 14:00:22 +0300 Subject: [PATCH 018/231] States discovery works in YouTrack repository --- .../tasks/youtrack/YouTrackRepository.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java index 5da18ef96d21..077f31cd493b 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java @@ -25,6 +25,7 @@ import com.intellij.tasks.impl.BaseRepository; import com.intellij.tasks.impl.BaseRepositoryImpl; import com.intellij.tasks.impl.LocalTaskImpl; import com.intellij.tasks.impl.TaskUtil; +import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.VersionComparatorUtil; @@ -47,10 +48,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.InputStream; import java.io.StringReader; -import java.util.Date; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author Dmitry Avdeev @@ -198,12 +196,23 @@ public class YouTrackRepository extends BaseRepositoryImpl { } @Override - public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception { - String s = myCustomStateNames.get(state); - if (StringUtil.isEmpty(s)) { - s = state.name(); - } - doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + s), true); + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { + doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + state.getId()), true); + } + + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + final HttpMethod method = doREST("/rest/issue/" + task.getId() + "/execute/intellisense?command=" + encodeUrl("state "), false); + final InputStream stream = method.getResponseBodyAsStream(); + final Element element = new SAXBuilder(false).build(stream).getRootElement(); + return ContainerUtil.map2Set(element.getChild("suggest").getChildren("item"), new Function() { + @Override + public CustomTaskState fun(Element element) { + final String stateName = element.getChildText("option"); + return new CustomTaskState(stateName, stateName); + } + }); } @Nullable From f24b2e2a5e13d10ee76e9625a1e6fd9ca007e659 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 12 Jan 2015 14:42:18 +0300 Subject: [PATCH 019/231] Remove the panel added in YouTrackRepositoryEditor because of IDEA-114203 --- .../tasks/youtrack/YouTrackOptionsTab.form | 84 ------------------- .../tasks/youtrack/YouTrackOptionsTab.java | 40 --------- .../tasks/youtrack/YouTrackRepository.java | 40 +-------- .../youtrack/YouTrackRepositoryEditor.java | 17 ---- 4 files changed, 4 insertions(+), 177 deletions(-) delete mode 100644 plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form delete mode 100644 plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form deleted file mode 100644 index 8dc52a33211a..000000000000 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.form +++ /dev/null @@ -1,84 +0,0 @@ - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java deleted file mode 100644 index fc084d293d52..000000000000 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackOptionsTab.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.intellij.tasks.youtrack; - -import com.intellij.ui.components.JBLabel; -import com.intellij.util.ui.UIUtil; - -import javax.swing.*; - -/** - * @author Mikhail Golubev - */ -public class YouTrackOptionsTab { - public static final String MESSAGE = "" + - "This option should be used only when \"Name\" property for \"State\" field " + - "was changed in server settings. It's not related to localized names of states." + - ""; - - private JTextField myInProgressState; - private JTextField myResolvedState; - private JPanel myRootPanel; - private JBLabel myNoteText; - - public YouTrackOptionsTab() { - myNoteText.setComponentStyle(UIUtil.ComponentStyle.SMALL); - myNoteText.setText(MESSAGE); - } - - public JTextField getInProgressState() { - return myInProgressState; - } - - public JTextField getResolvedState() { - return myResolvedState; - } - - public JPanel getRootPanel() { - return myRootPanel; - } - - -} diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java index 077f31cd493b..bb1f0c320bcb 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java @@ -29,8 +29,6 @@ import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.VersionComparatorUtil; -import com.intellij.util.xmlb.annotations.MapAnnotation; -import com.intellij.util.xmlb.annotations.Property; import com.intellij.util.xmlb.annotations.Tag; import org.apache.axis.utils.XMLChar; import org.apache.commons.httpclient.HttpClient; @@ -48,7 +46,9 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.InputStream; import java.io.StringReader; -import java.util.*; +import java.util.Date; +import java.util.List; +import java.util.Set; /** * @author Dmitry Avdeev @@ -57,13 +57,6 @@ import java.util.*; public class YouTrackRepository extends BaseRepositoryImpl { private String myDefaultSearch = "Assignee: me sort by: updated #Unresolved"; - private Map myCustomStateNames = new EnumMap(TaskState.class); - - // Default names for supported issues states - { - myCustomStateNames.put(TaskState.IN_PROGRESS, "In Progress"); - myCustomStateNames.put(TaskState.RESOLVED, "Fixed"); - } /** * for serialization @@ -85,7 +78,6 @@ public class YouTrackRepository extends BaseRepositoryImpl { private YouTrackRepository(YouTrackRepository other) { super(other); myDefaultSearch = other.getDefaultSearch(); - myCustomStateNames = new EnumMap(other.getCustomStateNames()); } public Task[] getIssues(@Nullable String request, int max, long since) throws Exception { @@ -324,9 +316,7 @@ public class YouTrackRepository extends BaseRepositoryImpl { public boolean equals(Object o) { if (!super.equals(o)) return false; YouTrackRepository repository = (YouTrackRepository)o; - if (!Comparing.equal(repository.getDefaultSearch(), getDefaultSearch())) return false; - if (!Comparing.equal(repository.getCustomStateNames(), getCustomStateNames())) return false; - return true; + return Comparing.equal(repository.getDefaultSearch(), getDefaultSearch()); } private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.youtrack.YouTrackRepository"); @@ -356,26 +346,4 @@ public class YouTrackRepository extends BaseRepositoryImpl { protected int getFeatures() { return super.getFeatures() | TIME_MANAGEMENT | STATE_UPDATING; } - - public void setCustomStateNames(Map customStateNames) { - myCustomStateNames.putAll(customStateNames); - } - - @Tag("customStates") - @Property(surroundWithTag = false) - @MapAnnotation( - surroundWithTag = false, - keyAttributeName = "state", - valueAttributeName = "name", - surroundKeyWithTag = false, - surroundValueWithTag = false - ) - - public Map getCustomStateNames() { - return myCustomStateNames; - } - - public void setCustomStateName(TaskState state, String name) { - myCustomStateNames.put(state, name); - } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java index db16ea5247bb..34ba0a773b5c 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepositoryEditor.java @@ -3,10 +3,8 @@ package com.intellij.tasks.youtrack; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; -import com.intellij.tasks.TaskState; import com.intellij.tasks.config.BaseRepositoryEditor; import com.intellij.tasks.youtrack.lang.YouTrackLanguage; import com.intellij.ui.EditorTextField; @@ -17,14 +15,12 @@ import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.Map; /** * @author Dmitry Avdeev */ public class YouTrackRepositoryEditor extends BaseRepositoryEditor { private static final Logger LOG = Logger.getInstance(YouTrackRepository.class); - private final YouTrackOptionsTab myOptions; private EditorTextField myDefaultSearch; private JBLabel mySearchLabel; @@ -36,17 +32,6 @@ public class YouTrackRepositoryEditor extends BaseRepositoryEditor states = myRepository.getCustomStateNames(); - myOptions.getInProgressState().setText(StringUtil.notNullize(states.get(TaskState.IN_PROGRESS))); - myOptions.getResolvedState().setText(StringUtil.notNullize(states.get(TaskState.RESOLVED))); - - installListener(myOptions.getInProgressState()); - installListener(myOptions.getResolvedState()); - - myTabbedPane.add("Options", myOptions.getRootPanel()); } @Override @@ -61,8 +46,6 @@ public class YouTrackRepositoryEditor extends BaseRepositoryEditor Date: Mon, 12 Jan 2015 16:00:53 +0300 Subject: [PATCH 020/231] Allow to move Trello card to another list when opening it --- .../com/intellij/tasks/TaskBundle.properties | 2 + .../tasks/trello/TrelloRepository.java | 42 ++++++++++++++++++- .../tasks/trello/TrelloRepositoryType.java | 2 +- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties b/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties index ce617cbf01ca..4d631b7c5d20 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/TaskBundle.properties @@ -23,3 +23,5 @@ youtrack.default.query=for: me sort by: updated #Unresolved bugzilla.failure.malformed.response=Cannot decode server response. Check that XML-RPC plugin is enabled. bugzilla.failure.no.version=Cannot find Bugzilla version. Check that URL ends with "xmlrpc.cgi". +## Trello +trello.failure.write.access.required=This action requires write access to your account. Please update authorization token in settings. diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java index 89d3e3d7d8f2..5a8a0c12b728 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java @@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; import com.intellij.tasks.TaskRepositoryType; @@ -41,16 +42,20 @@ import org.apache.http.*; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.utils.URIBuilder; import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -244,7 +249,12 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { if (myCurrentBoard == null || myCurrentBoard == UNSPECIFIED_BOARD) { throw new IllegalStateException("Board not set"); } - final URIBuilder url = new URIBuilder(getRestApiUrl("boards", myCurrentBoard.getId(), "lists")) + return fetchBoardLists(myCurrentBoard.getId()); + } + + @NotNull + private List fetchBoardLists(@NotNull String boardId) throws Exception { + final URIBuilder url = new URIBuilder(getRestApiUrl("boards", boardId, "lists")) .addParameter("fields", TrelloList.REQUIRED_FIELDS); return makeRequestAndDeserializeJsonResponse(url.build(), TrelloUtil.LIST_OF_LISTS_TYPE); } @@ -424,8 +434,36 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { return "https://api.trello.com"; } + @NotNull + @Override + public Set getAvailableTaskStates(@NotNull Task task) throws Exception { + final TrelloCard card = fetchCardById(task.getId()); + if (card != null) { + final List lists = fetchBoardLists(card.getIdBoard()); + final Set result = new HashSet(); + for (TrelloList list : lists) { + if (!list.getId().equals(card.getIdList())) { + result.add(new CustomTaskState(list.getId(), list.getName())); + } + } + return result; + } + return Collections.emptySet(); + } + + @Override + public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { + final URI url = new URIBuilder(getRestApiUrl("cards", task.getId(), "idList")).addParameter("value", state.getId()).build(); + final HttpResponse response = getHttpClient().execute(new HttpPut(url)); + if (response.getStatusLine() != null && + response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED && + EntityUtils.toString(response.getEntity()).trim().equals("unauthorized card permission requested")) { + throw new Exception(TaskBundle.message("trello.failure.write.access.required")); + } + } + @Override protected int getFeatures() { - return super.getFeatures() & ~NATIVE_SEARCH; + return super.getFeatures() & ~NATIVE_SEARCH | STATE_UPDATING; } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java index 86fca7a40be4..253a41f7bbca 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryType.java @@ -33,7 +33,7 @@ import javax.swing.*; public class TrelloRepositoryType extends BaseRepositoryType { public static final String DEVELOPER_KEY = "d6ec3709f7141007e150de64d4701181"; public static final String CLIENT_AUTHORIZATION_URL = - "https://trello.com/1/authorize?key=" + DEVELOPER_KEY +"&name=JetBrains&expiration=never&response_type=token"; + "https://trello.com/1/authorize?key=" + DEVELOPER_KEY +"&name=JetBrains&expiration=never&response_type=token&scope=read,write"; @NotNull @Override From 8ed654a1300a5e38f915015f803ffc8bef15007b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 12 Jan 2015 17:07:43 +0300 Subject: [PATCH 021/231] Allow to set custom task state on close, TaskRepository remembers most recently used state --- .../com/intellij/tasks/TaskRepository.java | 17 ++++- .../intellij/tasks/impl/BaseRepository.java | 12 ++++ .../tasks/actions/CloseTaskAction.java | 6 +- .../tasks/actions/CloseTaskDialog.form | 40 ++++++++--- .../tasks/actions/CloseTaskDialog.java | 70 ++++++++++++++++--- .../tasks/actions/OpenTaskDialog.form | 2 +- .../tasks/actions/OpenTaskDialog.java | 7 +- .../intellij/tasks/impl/TaskManagerImpl.java | 1 - 8 files changed, 129 insertions(+), 26 deletions(-) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 93c2f2dbf6ab..05ec1f0efbc4 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -186,18 +186,31 @@ public abstract class TaskRepository { } /** - * Remember state used for opening of task. + * Remember state used when opening task most recently. * @param state preferred task state */ public abstract void setPreferredOpenTaskState(@Nullable CustomTaskState state); /** - * Task state used last time for opening task. + * Task state that was used last time when opening task. * @return preferred task state */ @Nullable public abstract CustomTaskState getPreferredOpenTaskState(); + /** + * Remember state used when closing task most recently. + * @param state preferred task state + */ + public abstract void setPreferredCloseTaskState(@Nullable CustomTaskState state); + + /** + * Task state that was used last time when closing task. + * @return preferred task state + */ + @Nullable + public abstract CustomTaskState getPreferredCloseTaskState(); + /** * @param id task ID. Don't forget to define {@link #extractId(String)}, if your server uses not PROJECT-123 format for task IDs. * @return found task or {@code null} otherwise. Basically you should return {@code null} on e.g. 404 error and throw exception with diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java index 49ad62e2d1aa..0f67d4bae909 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepository.java @@ -42,6 +42,7 @@ public abstract class BaseRepository extends TaskRepository { protected boolean myUseHttpAuthentication; protected boolean myLoginAnonymously; protected CustomTaskState myPreferredOpenTaskState; + private CustomTaskState myPreferredCloseTaskState; public BaseRepository(TaskRepositoryType type) { super(type); @@ -148,6 +149,17 @@ public abstract class BaseRepository extends TaskRepository { return myPreferredOpenTaskState; } + @Override + public void setPreferredCloseTaskState(@Nullable CustomTaskState state) { + myPreferredCloseTaskState = state; + } + + @Nullable + @Override + public CustomTaskState getPreferredCloseTaskState() { + return myPreferredCloseTaskState; + } + @Nullable public String extractId(@NotNull String taskName) { Matcher matcher = PATTERN.matcher(taskName); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java index 6863eef78510..7bf2afa94b2f 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskAction.java @@ -41,11 +41,13 @@ public class CloseTaskAction extends BaseTaskAction { LocalTask task = taskManager.getActiveTask(); CloseTaskDialog dialog = new CloseTaskDialog(project, task); if (dialog.showAndGet()) { - if (dialog.isCloseIssue()) { + final CustomTaskState taskState = dialog.getCloseIssueState(); + if (taskState != null) { try { TaskRepository repository = task.getRepository(); assert repository != null; - repository.setTaskState(task, TaskState.RESOLVED); + repository.setTaskState(task, taskState); + repository.setPreferredCloseTaskState(taskState); } catch (Exception e1) { Messages.showErrorDialog(project, e1.getMessage(), "Cannot Resolve Issue"); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form index 0c8600a9785b..faa9841f61c6 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form @@ -3,7 +3,7 @@ - + @@ -52,14 +52,6 @@ - - - - - - - - @@ -73,6 +65,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java index fa9879c05fe0..d194a073fbd7 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java @@ -16,45 +16,90 @@ package com.intellij.tasks.actions; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.vcs.VcsType; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.LocalTask; import com.intellij.tasks.TaskManager; import com.intellij.tasks.TaskRepository; -import com.intellij.tasks.TaskState; import com.intellij.tasks.impl.TaskManagerImpl; +import com.intellij.tasks.impl.TaskUiUtil; import com.intellij.tasks.impl.TaskUtil; +import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.Set; /** * @author Dmitry Avdeev */ public class CloseTaskDialog extends DialogWrapper { + private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); private JCheckBox myCommitChanges; - private JCheckBox myCloseIssue; private JPanel myPanel; private JLabel myTaskLabel; private JBCheckBox myMergeBranches; private JPanel myVcsPanel; + private ComboBox myStateComboBox; + private JLabel myStateComboBoxLabel; private final TaskManagerImpl myTaskManager; - public CloseTaskDialog(Project project, LocalTask task) { + public CloseTaskDialog(Project project, final LocalTask task) { super(project, false); setTitle("Close Task"); myTaskLabel.setText(TaskUtil.getTrimmedSummary(task)); myTaskLabel.setIcon(task.getIcon()); - TaskRepository repository = task.getRepository(); - boolean visible = task.isIssue() && TaskUtil.isStateSupported(repository, TaskState.RESOLVED); - myCloseIssue.setVisible(visible); + final TaskRepository repository = task.getRepository(); + myStateComboBox.setRenderer(new ListCellRendererWrapper() { + @Override + public void customize(JList list, CustomTaskState value, int index, boolean selected, boolean hasFocus) { + if (value != null) { + setText(value.getPresentableName()); + } + else { + setText("-- no states available --"); + } + } + }); + + // Capture correct modality state + if (task.isIssue() && repository != null && repository.isSupported(TaskRepository.STATE_UPDATING)) { + // Find out proper way to determine modality state here + new TaskUiUtil.ComboBoxUpdater(project, "Fetching available task states...", myStateComboBox) { + @NotNull + @Override + protected Set fetch(@NotNull ProgressIndicator indicator) throws Exception { + return repository.getAvailableTaskStates(task); + } + + @Nullable + @Override + public CustomTaskState getSelectedItem() { + return repository.getPreferredCloseTaskState(); + } + + @Nullable + @Override + public CustomTaskState getExtraItem() { + return DO_NOT_UPDATE_STATE; + } + }.queue(); + } + else { + myStateComboBoxLabel.setVisible(false); + myStateComboBox.setVisible(false); + } myTaskManager = (TaskManagerImpl)TaskManager.getManager(project); - myCloseIssue.setSelected(visible && myTaskManager.getState().closeIssue); if (myTaskManager.isVcsEnabled()) { myCommitChanges.setEnabled(!task.getChangeLists().isEmpty()); @@ -78,8 +123,10 @@ public class CloseTaskDialog extends DialogWrapper { return myPanel; } - boolean isCloseIssue() { - return myCloseIssue.isSelected(); + @Nullable + CustomTaskState getCloseIssueState() { + final CustomTaskState selected = (CustomTaskState)myStateComboBox.getSelectedItem(); + return selected == null || selected == DO_NOT_UPDATE_STATE ? null : selected; } boolean isCommitChanges() { @@ -92,7 +139,6 @@ public class CloseTaskDialog extends DialogWrapper { @Override protected void doOKAction() { - myTaskManager.getState().closeIssue = isCloseIssue(); if (myCommitChanges.isEnabled()) { myTaskManager.getState().commitChanges = isCommitChanges(); } @@ -101,4 +147,8 @@ public class CloseTaskDialog extends DialogWrapper { } super.doOKAction(); } + + private void createUIComponents() { + myStateComboBox = new ComboBox(300); + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index 69fcfb993d05..3f506464dc95 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -37,7 +37,7 @@ - + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 0efa5396b424..b88b296fd5a6 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -68,6 +68,7 @@ public class OpenTaskDialog extends DialogWrapper { private JBLabel myFromLabel; private ComboBox myBranchFrom; private ComboBox myStateComboBox; + private JLabel myStateComboBoxLabel; private final Project myProject; private final Task myTask; @@ -101,7 +102,7 @@ public class OpenTaskDialog extends DialogWrapper { // Capture correct modality state final TaskRepository repository = myTask.getRepository(); - if (repository != null) { + if (myTask.isIssue() && repository != null && repository.isSupported(TaskRepository.STATE_UPDATING)) { // Find out proper way to determine modality state here new ComboBoxUpdater(myProject, "Fetching available task states...", myStateComboBox) { @NotNull @@ -123,6 +124,10 @@ public class OpenTaskDialog extends DialogWrapper { } }.queue(); } + else { + myStateComboBoxLabel.setVisible(false); + myStateComboBox.setVisible(false); + } TaskManagerImpl.Config state = taskManager.getState(); myClearContext.setSelected(state.clearContext); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index 94f940af9c5a..745e3bb93719 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -1030,7 +1030,6 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe public boolean createBranch = true; // close task options - public boolean closeIssue = true; public boolean commitChanges = true; public boolean mergeBranch = true; From 842d61aa3bcf87892b909e7eb64bef5d7b5c4ca9 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 12 Jan 2015 17:51:12 +0300 Subject: [PATCH 022/231] Update JiraIntegrationTest#testSetTaskState to use CustomTaskStates --- .../tasks/integration/JiraIntegrationTest.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java index a3d99c33228c..9eb47a02c0b3 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java @@ -18,18 +18,13 @@ package com.intellij.tasks.integration; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.intellij.tasks.Task; -import com.intellij.tasks.TaskBundle; -import com.intellij.tasks.TaskManagerTestCase; -import com.intellij.tasks.TaskState; +import com.intellij.tasks.*; import com.intellij.tasks.config.TaskSettings; import com.intellij.tasks.impl.LocalTaskImpl; import com.intellij.tasks.impl.TaskUtil; import com.intellij.tasks.jira.JiraRepository; import com.intellij.tasks.jira.JiraRepositoryType; import com.intellij.tasks.jira.JiraVersion; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.jetbrains.annotations.NonNls; @@ -52,6 +47,8 @@ public class JiraIntegrationTest extends TaskManagerTestCase { * JIRA 5.0.6, REST API 2.0 */ @NonNls private static final String JIRA_5_TEST_SERVER_URL = "http://trackers-tests.labs.intellij.net:8015"; + public static final CustomTaskState REOPENED_CUSTOM_STATE = new CustomTaskState("3", "Reopened"); + public static final CustomTaskState RESOLVED_CUSTOM_STATE = new CustomTaskState("5:Fixed", "Fixed"); private JiraRepository myRepository; @@ -167,18 +164,18 @@ public class JiraIntegrationTest extends TaskManagerTestCase { assertNotNull("Test task not found", task); // set required initial state, if was left wrong if (task.getState() != TaskState.REOPENED) { - myRepository.setTaskState(task, TaskState.REOPENED); + myRepository.setTaskState(task, REOPENED_CUSTOM_STATE); } try { //assertEquals("Wrong initial state of test issue: " + key, TaskState.REOPENED, task.getState()); - myRepository.setTaskState(task, TaskState.RESOLVED); + myRepository.setTaskState(task, RESOLVED_CUSTOM_STATE); task = myRepository.findTask(key); assertEquals(task.getState(), TaskState.RESOLVED); } finally { try { // always attempt to restore original state of the issue - myRepository.setTaskState(task, TaskState.REOPENED); + myRepository.setTaskState(task, REOPENED_CUSTOM_STATE); } catch (Exception ignored) { // empty From eea3c34032cd7e917bd9e5e2ba3182517ba94b9b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 12 Jan 2015 19:02:08 +0300 Subject: [PATCH 023/231] Add test for state updates in TrelloIntegrationTest --- .../live/TrelloIntegrationTest.java | 90 +++++++++++++++---- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java index 654b51261d88..d9150d342ce2 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java @@ -2,8 +2,10 @@ package com.intellij.tasks.integration.live; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.trello.TrelloRepository; import com.intellij.tasks.trello.TrelloRepositoryType; +import com.intellij.tasks.trello.TrelloTask; import com.intellij.tasks.trello.model.*; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -22,8 +24,9 @@ import static com.intellij.tasks.trello.model.TrelloLabel.LabelColor.*; */ public class TrelloIntegrationTest extends LiveIntegrationTestCase { - private static final String BOARD_1_NAME = "Board 1"; - private static final String BOARD_1_ID = "53c416a8a6e5a78753562043"; + // Basic functionality (searching, filtering, etc.) + private static final String BASIC_FUNCTIONALITY_BOARD_NAME = "Basic Functionality"; + private static final String BASIC_FUNCTIONALITY_BOARD_ID = "53c416a8a6e5a78753562043"; private static final String LIST_1_1_NAME = "List 1-1"; private static final String LIST_1_1_ID = "53c416a8a6e5a78753562044"; @@ -31,6 +34,17 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase boards = myRepository.fetchUserBoards(); - assertEquals(2, boards.size()); - assertObjectsNamed("All boards of the user should be included", boards, "Board 1", "Board 2"); + assertEquals(3, boards.size()); + assertObjectsNamed("All boards of the user should be included", boards, + BASIC_FUNCTIONALITY_BOARD_NAME, LABELS_AND_COLORS_BOARD_NAME, STATE_UPDATES_BOARD_NAME); } public void testFetchListsOfBoard() throws Exception { - TrelloBoard selectedBoard = myRepository.fetchBoardById(BOARD_1_ID); + TrelloBoard selectedBoard = myRepository.fetchBoardById(BASIC_FUNCTIONALITY_BOARD_ID); assertNotNull(selectedBoard); myRepository.setCurrentBoard(selectedBoard); List lists = myRepository.fetchBoardLists(); @@ -88,7 +103,7 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase fetchCards(@Nullable String boardId, @Nullable String listId, boolean withClosed) throws Exception { if (boardId != null) { - TrelloBoard selectedBoard = myRepository.fetchBoardById(BOARD_1_ID); + TrelloBoard selectedBoard = myRepository.fetchBoardById(BASIC_FUNCTIONALITY_BOARD_ID); assertNotNull(selectedBoard); myRepository.setCurrentBoard(selectedBoard); } @@ -108,24 +123,24 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase cards = fetchCards(BOARD_1_ID, null, true); + List cards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, null, true); assertObjectsNamed("All cards of the board should be included", cards, "Card 1-1-1", "Card 1-1-2", "Card 1-2-1", "Card 1-3-1", "Archived Card"); } public void testCardsFilteringByMembership() throws Exception { myRepository.setIncludeAllCards(true); - List allCards = fetchCards(BOARD_1_ID, LIST_1_1_ID, true); + List allCards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, LIST_1_1_ID, true); assertObjectsNamed("All cards of the list should be included", allCards, "Card 1-1-1", "Card 1-1-2", "Archived Card"); myRepository.setIncludeAllCards(false); - List assignedCards = fetchCards(BOARD_1_ID, LIST_1_1_ID, true); + List assignedCards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, LIST_1_1_ID, true); assertObjectsNamed("Only cards of the list assigned to user should be included", assignedCards, "Card 1-1-1"); } public void testCardsFilteringByStatus() throws Exception { myRepository.setIncludeAllCards(true); - List allCards = fetchCards(BOARD_1_ID, LIST_1_1_NAME, true); + List allCards = fetchCards(BASIC_FUNCTIONALITY_BOARD_ID, LIST_1_1_NAME, true); assertObjectsNamed("All cards of the list should be included", allCards, "Card 1-1-1", "Card 1-1-2", "Archived Card"); TrelloCard card = ContainerUtil.find(allCards, new Condition() { @@ -139,8 +154,17 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase labels = card.getLabels(); @@ -156,13 +180,41 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase states = myRepository.getAvailableTaskStates(task); + assertEquals(1, states.size()); + final CustomTaskState inProgressState = states.iterator().next(); + assertEquals(IN_PROGRESS_LIST_ID, inProgressState.getId()); + assertEquals("In Progress", inProgressState.getPresentableName()); + + // Backlog -> In Progress + myRepository.setTaskState(task, inProgressState); + card = myRepository.fetchCardById(FEATURE_CARD_ID); + assertNotNull(card); + assertEquals(STATE_UPDATES_BOARD_ID, card.getIdBoard()); + assertEquals(IN_PROGRESS_LIST_ID, card.getIdList()); + + // Discover "Backlog" list + task = new TrelloTask(card, myRepository); + states = myRepository.getAvailableTaskStates(task); + assertEquals(1, states.size()); + final CustomTaskState backlogState = states.iterator().next(); + assertEquals(BACKLOG_LIST_ID, backlogState.getId()); + assertEquals("Backlog", backlogState.getPresentableName()); + + // In Progress -> Backlog + myRepository.setTaskState(task, backlogState); + card = myRepository.fetchCardById(FEATURE_CARD_ID); + assertNotNull(card); + assertEquals(STATE_UPDATES_BOARD_ID, card.getIdBoard()); + assertEquals(BACKLOG_LIST_ID, card.getIdList()); } static void assertObjectsNamed(@NotNull String message, @NotNull Collection objects, @NotNull String... names) { From 91beb1c0e3f2f5c909f28920b1dd8253554eb24b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 13 Jan 2015 16:27:57 +0300 Subject: [PATCH 024/231] Add test for state updates in YouTrackRepository. Also it correctly releases connections now --- .../com/intellij/tasks/CustomTaskState.java | 5 + .../tasks/youtrack/YouTrackRepository.java | 148 +++++++++++------- .../integration/YouTrackIntegrationTest.java | 59 +++++++ 3 files changed, 157 insertions(+), 55 deletions(-) create mode 100644 plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java index dbae96362d79..cd479e90aee7 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java @@ -83,4 +83,9 @@ public class CustomTaskState { public void setPredefined(boolean predefined) { myPredefined = predefined; } + + @Override + public String toString() { + return "CustomTaskState(id='" + myId + '\'' + ", name='" + myPresentableName + '\'' + ", myPredefined=" + myPredefined + ')'; + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java index bb1f0c320bcb..c67fa6834368 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java @@ -42,6 +42,7 @@ import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.io.InputStream; @@ -88,39 +89,44 @@ public class YouTrackRepository extends BaseRepositoryImpl { } String requestUrl = "/rest/project/issues/?filter=" + encodeUrl(query) + "&max=" + max + "&updatedAfter" + since; HttpMethod method = doREST(requestUrl, false); - InputStream stream = method.getResponseBodyAsStream(); - - // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984 - String s = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); - for (int i = 0; i < s.length(); i++) { - if (!XMLChar.isValid(s.charAt(i))) { - s = s.replace(s.charAt(i), ' '); - } - } - - Element element; try { - //InputSource source = new InputSource(stream); - //source.setEncoding("UTF-8"); - //element = new SAXBuilder(false).build(source).getRootElement(); - element = new SAXBuilder(false).build(new StringReader(s)).getRootElement(); - } - catch (JDOMException e) { - LOG.error("Can't parse YouTrack response for " + requestUrl, e); - throw e; - } - if ("error".equals(element.getName())) { - throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'"); - } + InputStream stream = method.getResponseBodyAsStream(); - List children = element.getChildren("issue"); - - final List tasks = ContainerUtil.mapNotNull(children, new NullableFunction() { - public Task fun(Element o) { - return createIssue(o); + // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984 + String s = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET); + for (int i = 0; i < s.length(); i++) { + if (!XMLChar.isValid(s.charAt(i))) { + s = s.replace(s.charAt(i), ' '); + } } - }); - return tasks.toArray(new Task[tasks.size()]); + + Element element; + try { + //InputSource source = new InputSource(stream); + //source.setEncoding("UTF-8"); + //element = new SAXBuilder(false).build(source).getRootElement(); + element = new SAXBuilder(false).build(new StringReader(s)).getRootElement(); + } + catch (JDOMException e) { + LOG.error("Can't parse YouTrack response for " + requestUrl, e); + throw e; + } + if ("error".equals(element.getName())) { + throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'"); + } + + List children = element.getChildren("issue"); + + final List tasks = ContainerUtil.mapNotNull(children, new NullableFunction() { + public Task fun(Element o) { + return createIssue(o); + } + }); + return tasks.toArray(new Task[tasks.size()]); + } + finally { + method.releaseConnection(); + } } @Nullable @@ -143,10 +149,16 @@ public class YouTrackRepository extends BaseRepositoryImpl { method.addParameter("password", getPassword()); client.getParams().setContentCharset("UTF-8"); client.executeMethod(method); - if (method.getStatusCode() != 200) { - throw new Exception("Cannot login: HTTP status code " + method.getStatusCode()); + String response; + try { + if (method.getStatusCode() != 200) { + throw new Exception("Cannot login: HTTP status code " + method.getStatusCode()); + } + response = method.getResponseBodyAsString(1000); + } + finally { + method.releaseConnection(); } - String response = method.getResponseBodyAsString(1000); if (response == null) { throw new NullPointerException(); } @@ -163,12 +175,23 @@ public class YouTrackRepository extends BaseRepositoryImpl { @Nullable public Task findTask(@NotNull String id) throws Exception { - HttpMethod method = doREST("/rest/issue/byid/" + id, false); - InputStream stream = method.getResponseBodyAsStream(); - Element element = new SAXBuilder(false).build(stream).getRootElement(); + final Element element = fetchRequestAsElement(id); return element.getName().equals("issue") ? createIssue(element) : null; } + @TestOnly + @NotNull + public Element fetchRequestAsElement(@NotNull String id) throws Exception { + final HttpMethod method = doREST("/rest/issue/byid/" + id, false); + try { + final InputStream stream = method.getResponseBodyAsStream(); + return new SAXBuilder(false).build(stream).getRootElement(); + } + finally { + method.releaseConnection(); + } + } + HttpMethod doREST(String request, boolean post) throws Exception { HttpClient client = login(new PostMethod(getUrl() + "/rest/user/login")); @@ -189,22 +212,27 @@ public class YouTrackRepository extends BaseRepositoryImpl { @Override public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception { - doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + state.getId()), true); + doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + state.getId()), true).releaseConnection(); } @NotNull @Override public Set getAvailableTaskStates(@NotNull Task task) throws Exception { final HttpMethod method = doREST("/rest/issue/" + task.getId() + "/execute/intellisense?command=" + encodeUrl("state "), false); - final InputStream stream = method.getResponseBodyAsStream(); - final Element element = new SAXBuilder(false).build(stream).getRootElement(); - return ContainerUtil.map2Set(element.getChild("suggest").getChildren("item"), new Function() { - @Override - public CustomTaskState fun(Element element) { - final String stateName = element.getChildText("option"); - return new CustomTaskState(stateName, stateName); - } - }); + try { + final InputStream stream = method.getResponseBodyAsStream(); + final Element element = new SAXBuilder(false).build(stream).getRootElement(); + return ContainerUtil.map2Set(element.getChild("suggest").getChildren("item"), new Function() { + @Override + public CustomTaskState fun(Element element) { + final String stateName = element.getChildText("option"); + return new CustomTaskState(stateName, stateName); + } + }); + } + finally { + method.releaseConnection(); + } } @Nullable @@ -325,20 +353,30 @@ public class YouTrackRepository extends BaseRepositoryImpl { public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception { checkVersion(); final HttpMethod method = doREST("/rest/issue/execute/" + task.getId() + "?command=work+Today+" + timeSpent.replaceAll(" ", "+") + "+" + comment, true); - if (method.getStatusCode() != 200) { - InputStream stream = method.getResponseBodyAsStream(); - String message = new SAXBuilder(false).build(stream).getRootElement().getText(); - throw new Exception(message); + try { + if (method.getStatusCode() != 200) { + InputStream stream = method.getResponseBodyAsStream(); + String message = new SAXBuilder(false).build(stream).getRootElement().getText(); + throw new Exception(message); + } + } + finally { + method.releaseConnection(); } } private void checkVersion() throws Exception { HttpMethod method = doREST("/rest/workflow/version", false); - InputStream stream = method.getResponseBodyAsStream(); - Element element = new SAXBuilder(false).build(stream).getRootElement(); - final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0; - if (!timeTrackingAvailable) { - throw new Exception("This version of Youtrack the time tracking is not supported"); + try { + InputStream stream = method.getResponseBodyAsStream(); + Element element = new SAXBuilder(false).build(stream).getRootElement(); + final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0; + if (!timeTrackingAvailable) { + throw new Exception("This version of Youtrack the time tracking is not supported"); + } + } + finally { + method.releaseConnection(); } } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java new file mode 100644 index 000000000000..f4577b8b1327 --- /dev/null +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java @@ -0,0 +1,59 @@ +package com.intellij.tasks.integration; + +import com.intellij.tasks.CustomTaskState; +import com.intellij.tasks.Task; +import com.intellij.tasks.TaskManagerTestCase; +import com.intellij.tasks.youtrack.YouTrackRepository; +import com.intellij.tasks.youtrack.YouTrackRepositoryType; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jdom.Element; + +import java.util.List; +import java.util.Set; + +/** + * @author Mikhail Golubev + */ +public class YouTrackIntegrationTest extends TaskManagerTestCase { + private static final String YOUTRACK_4_TEST_SERVER_URL = "http://trackers-tests.labs.intellij.net:8067"; + + private static final String REQUEST_WITH_CUSTOM_STATES_ID = "YT4CS-1"; + private static final CustomTaskState NORTH_STATE = new CustomTaskState("North", "North"); + private static final CustomTaskState SUBMITTED_STATE = new CustomTaskState("Submitted", "Submitted"); + + private YouTrackRepository myRepository; + + public void testCustomTaskStates() throws Exception { + final Task task = myRepository.findTask(REQUEST_WITH_CUSTOM_STATES_ID); + assertNotNull(task); + + final Set states = myRepository.getAvailableTaskStates(task); + final List stateNames = ContainerUtil.map(states, new Function() { + @Override + public String fun(CustomTaskState state) { + return state.getPresentableName(); + } + }); + assertContainsElements(stateNames, "North", "South"); + + // ? -> North + myRepository.setTaskState(task, NORTH_STATE); + Element element = myRepository.fetchRequestAsElement(REQUEST_WITH_CUSTOM_STATES_ID); + assertEquals("North", element.getAttributeValue("state")); + + // North -> Submitted + myRepository.setTaskState(task, SUBMITTED_STATE); + element = myRepository.fetchRequestAsElement(REQUEST_WITH_CUSTOM_STATES_ID); + assertEquals("Submitted", element.getAttributeValue("state")); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + myRepository = new YouTrackRepository(new YouTrackRepositoryType()); + myRepository.setUrl(YOUTRACK_4_TEST_SERVER_URL); + myRepository.setUsername("buildtest"); + myRepository.setPassword("buildtest"); + } +} From 2d7ff4d318decd3b8bd1e6221e92267e3404419d Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 14 Jan 2015 18:39:17 +0200 Subject: [PATCH 025/231] merged ReformatCodeActionInEditorTest into MultiActionCodeProcessorTest, test data moved. Fixed compilation and other minor after merge issues. --- ...sChangedTextReformatAndOptimize_after.java | 18 --- ...ChangedTextReformatAndOptimize_before.java | 22 ---- .../vcsChangedTextReformat_after.java | 19 --- .../vcsChangedTextReformat_before.java | 18 --- .../selectedTextAndOptimizeImports_after.java | 0 ...selectedTextAndOptimizeImports_before.java | 0 .../selectionReformat_after.java | 0 .../selectionReformat_before.java | 0 .../wholeFileReformatAndOptimize_after.java | 0 .../wholeFileReformatAndOptimize_before.java | 0 .../wholeFileReformat_after.java | 0 .../wholeFileReformat_before.java | 0 .../actions/MultiActionCodeProcessorTest.java | 75 +++++++---- .../ReformatCodeActionInEditorTest.java | 121 ------------------ .../actions/ReformatCodeActionTest.java | 31 +---- .../actions/FormatChangedTextUtil.java | 12 +- .../actions/RearrangeCodeProcessor.java | 18 +-- 17 files changed, 58 insertions(+), 276 deletions(-) delete mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java delete mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java delete mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java delete mode 100644 java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/selectedTextAndOptimizeImports_after.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/selectedTextAndOptimizeImports_before.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/selectionReformat_after.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/selectionReformat_before.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/wholeFileReformatAndOptimize_after.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/wholeFileReformatAndOptimize_before.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/wholeFileReformat_after.java (100%) rename java/java-tests/testData/actions/{codeProcessor => reformatFileInEditor}/wholeFileReformat_before.java (100%) delete mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java deleted file mode 100644 index 122700a59862..000000000000 --- a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_after.java +++ /dev/null @@ -1,18 +0,0 @@ -import java.util.ArrayList; -import java.util.List; - - -public class Test { - - public static void main(String[] args) { - List list = new ArrayList(); - int a = 3; - -int b = 3; - } - - - public void test() { - } - -} diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java deleted file mode 100644 index 878031804ea0..000000000000 --- a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformatAndOptimize_before.java +++ /dev/null @@ -1,22 +0,0 @@ -import java.util.HashMap; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.HashSet; - - -public class Test { - - public static void main(String[] args) { - List list = new ArrayList(); -int a = 3; - -int b = 3; - } - - - -public void test() { -} - -} diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java deleted file mode 100644 index bf2d0b708392..000000000000 --- a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_after.java +++ /dev/null @@ -1,19 +0,0 @@ -public class Test { - - int a = 3; - int b = 12; - -long t = 12; - - public void test() { - - int a = 3; - int b = 4; - } - - int rest = -12; - - public void run() { - } - -} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java b/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java deleted file mode 100644 index d837a92dbf22..000000000000 --- a/java/java-tests/testData/actions/codeProcessor/vcsChangedTextReformat_before.java +++ /dev/null @@ -1,18 +0,0 @@ -public class Test { - - int a = 3; - int b = 12; - -long t = 12; - - public void test() { - - int a = 3; - int b = 4; - } - - int rest = -12; - -public void run() {} - -} \ No newline at end of file diff --git a/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_after.java b/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_after.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_after.java rename to java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_after.java diff --git a/java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_before.java b/java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_before.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/selectedTextAndOptimizeImports_before.java rename to java/java-tests/testData/actions/reformatFileInEditor/selectedTextAndOptimizeImports_before.java diff --git a/java/java-tests/testData/actions/codeProcessor/selectionReformat_after.java b/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_after.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/selectionReformat_after.java rename to java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_after.java diff --git a/java/java-tests/testData/actions/codeProcessor/selectionReformat_before.java b/java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_before.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/selectionReformat_before.java rename to java/java-tests/testData/actions/reformatFileInEditor/selectionReformat_before.java diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_after.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_after.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_after.java rename to java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_after.java diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_before.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_before.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/wholeFileReformatAndOptimize_before.java rename to java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformatAndOptimize_before.java diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_after.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_after.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/wholeFileReformat_after.java rename to java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_after.java diff --git a/java/java-tests/testData/actions/codeProcessor/wholeFileReformat_before.java b/java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_before.java similarity index 100% rename from java/java-tests/testData/actions/codeProcessor/wholeFileReformat_before.java rename to java/java-tests/testData/actions/reformatFileInEditor/wholeFileReformat_before.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java index f457bf794fee..d43731e93b83 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java @@ -18,7 +18,9 @@ package com.intellij.codeInsight.actions; import com.intellij.JavaTestUtil; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.CaretModel; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiFile; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -31,38 +33,31 @@ public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtur @Override protected String getTestDataPath() { - return JavaTestUtil.getJavaTestDataPath() + "/actions/codeProcessor/"; - } - - @Override - public void setUp() throws Exception { - super.setUp(); + return JavaTestUtil.getJavaTestDataPath() + "/actions/reformatFileInEditor/"; } @Override public void tearDown() throws Exception { - myFixture.getFile().putUserData(FormatChangedTextUtil.CHANGED_RANGES, null); + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); super.tearDown(); } public void doTest(LayoutCodeOptions options) { - myFixture.configureByFile(getTestDataPath() + getTestName(true) + "_before.java"); - CodeProcessor processor = new CodeProcessor(myFixture.getFile(), myFixture.getEditor(), options); - + CharSequence revisionContent = null; if (options.getTextRangeType() == VCS_CHANGED_TEXT) { - CaretModel model = myFixture.getEditor().getCaretModel(); - List ranges = ContainerUtil.mapNotNull(model.getAllCarets(), new Function() { - @Override - public TextRange fun(Caret caret) { - if (caret.hasSelection()) { - return new TextRange(caret.getSelectionStart(), caret.getSelectionEnd()); - } - return null; - } - }); - myFixture.getFile().putUserData(FormatChangedTextUtil.CHANGED_RANGES, ranges); + myFixture.configureByFile(getTestName(true) + "_revision.java"); + PsiFile file = myFixture.getFile(); + Document document = myFixture.getDocument(file); + revisionContent = document.getCharsSequence(); } + myFixture.configureByFile(getTestName(true) + "_before.java"); + if (revisionContent != null) { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, revisionContent); + } + + CodeProcessor processor = new CodeProcessor(myFixture.getFile(), myFixture.getEditor(), options); + processor.processCode(); myFixture.checkResultByFile(getTestName(true) + "_after.java"); } @@ -75,10 +70,6 @@ public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtur doTest(new ReformatCodeRunOptions(WHOLE_FILE)); } - public void testVcsChangedTextReformat() { - doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT)); - } - public void testWholeFileReformatAndOptimize() { doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true)); } @@ -87,7 +78,35 @@ public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtur doTest(new ReformatCodeRunOptions(SELECTED_TEXT).setOptimizeImports(true)); } - //public void testVcsChangedTextReformatAndOptimize() { - // doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true)); - //} + public void testFormatWholeFile() { + doTest(new ReformatCodeRunOptions(WHOLE_FILE)); + } + + public void testFormatOptimizeWholeFile() { + doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true)); + } + + public void testFormatOptimizeRearrangeWholeFile() { + doTest(new ReformatCodeRunOptions(WHOLE_FILE).setOptimizeImports(true).setRearrangeCode(true)); + } + + public void testFormatSelection() { + doTest(new ReformatCodeRunOptions(SELECTED_TEXT)); + } + + public void testFormatRearrangeSelection() { + doTest(new ReformatCodeRunOptions(SELECTED_TEXT).setRearrangeCode(true)); + } + + public void testFormatVcsChanges() { + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT)); + } + + public void testFormatOptimizeVcsChanges() { + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true)); + } + + public void testFormatOptimizeRearrangeVcsChanges() { + doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true).setRearrangeCode(true)); + } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java deleted file mode 100644 index 0dd2bcebc27d..000000000000 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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.codeInsight.actions; - -import com.intellij.JavaTestUtil; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.psi.PsiFile; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class ReformatCodeActionInEditorTest extends LightCodeInsightFixtureTestCase { - - @Override - protected String getTestDataPath() { - return JavaTestUtil.getJavaTestDataPath() + "/actions/reformatFileInEditor/"; - } - - public void doTest(@NotNull ReformatFilesOptions options) { - setOptions(options); - - String before = null; - if (options.isProcessOnlyChangedText()) { - myFixture.configureByFile(getTestName(true) + "_revision.java"); - PsiFile file = myFixture.getFile(); - Document document = myFixture.getDocument(file); - before = document.getText(); - } - - myFixture.configureByFile(getTestName(true) + "_before.java"); - - if (before != null) { - myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, before); - } - - final String actionId = IdeActions.ACTION_EDITOR_REFORMAT; - AnAction action = ActionManager.getInstance().getAction(actionId); - - AnActionEvent event = createEventFor(action, getProject(), myFixture.getEditor()); - - action.actionPerformed(event); - myFixture.checkResultByFile(getTestName(true) + "_after.java"); - } - - @Override - public void tearDown() throws Exception { - myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); - super.tearDown(); - } - - protected AnActionEvent createEventFor(@NotNull AnAction action, @NotNull final Project project, @NotNull final Editor editor) { - return new AnActionEvent(null, new DataContext() { - @Nullable - @Override - public Object getData(@NonNls String dataId) { - if (CommonDataKeys.PROJECT.is(dataId)) return project; - if (CommonDataKeys.EDITOR.is(dataId)) return editor; - return null; - } - }, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0); - } - - protected void setOptions(ReformatFilesOptions options) { - ReformatCodeAction.setTestOptions(options); - } - - public void testFormatWholeFile() { - doTest(new MockReformatFileSettings().setProcessWholeFile(true)); - } - - public void testFormatOptimizeWholeFile() { - doTest(new MockReformatFileSettings().setProcessWholeFile(true).setOptimizeImports(true)); - } - - public void testFormatOptimizeRearrangeWholeFile() { - doTest(new MockReformatFileSettings().setProcessWholeFile(true).setOptimizeImports(true).setRearrange(true)); - } - - public void testFormatSelection() { - doTest(new MockReformatFileSettings().setProcessWholeFile(false)); - } - - public void testFormatRearrangeSelection() { - doTest(new MockReformatFileSettings().setProcessWholeFile(false).setRearrange(true)); - } - - public void testFormatVcsChanges() { - doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true)); - } - - public void testFormatOptimizeVcsChanges() { - doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true).setOptimizeImports(true)); - } - - public void testFormatOptimizeRearrangeVcsChanges() { - doTest(new MockReformatFileSettings().setProcessOnlyChangedText(true).setOptimizeImports(true).setRearrange(true)); - } - -} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java index b43059389253..5d8e8c95caa9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java @@ -34,30 +34,11 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { public void testReformatAndOptimizeMultipleFiles() throws IOException { List files = createTestFiles(getTempRootDirectory(), classNames); - - //todo mock this guy - //LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); - + injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); performReformatActionOnSelectedFiles(files); checkFormationAndImportsOptimizationFor(files); } - public void testReformatSingleSelected_FileWithoutEditor() throws IOException { - //todo fill - } - - public void testReformatAndOptimizeFileFromEditor() throws IOException { - List files = createTestFiles(getTempRootDirectory(), classNames); - injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true)); - - PsiFile fileToFormat = files.get(0); - List shouldNotBeFormatted = files.subList(1, files.size()); - - performReformatActionOnFileInEditor(fileToFormat); - checkFormationAndImportsOptimizationFor(Arrays.asList(fileToFormat)); - checkNoProcessingWasPerformedOn(shouldNotBeFormatted); - } - public void testOptimizeAndReformatOnlySelectedFiles() throws IOException { List files = createTestFiles(getTempRootDirectory(), classNames); List forProcessing = ContainerUtil.newArrayList(files.get(0), files.get(1)); @@ -71,10 +52,6 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkNoProcessingWasPerformedOn(noProcessing); } - public void testOptimizeAndReformat_AllFilesInDirectoryIncludeSubdirs() throws IOException { - //todo create tests for AbstractLayoutCodeProcessor - } - public void testOptimizeAndReformatInModule() throws IOException { Module module = createModuleWithSourceRoot("newModule"); VirtualFile srcDir = ModuleRootManager.getInstance(module).getSourceRoots()[0]; @@ -85,10 +62,4 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest { checkFormationAndImportsOptimizationFor(files); } - - - - - - } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 1a38026975af..2a831ed87a0a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -54,9 +54,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class FormatChangedTextUtil { - public static final Key TEST_REVISION_CONTENT = Key.create("test.revision.content"); + public static final Key TEST_REVISION_CONTENT = Key.create("test.revision.content"); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil"); - protected static final Key> CHANGED_RANGES = Key.create("changed.ranges.since.last.revision"); private FormatChangedTextUtil() { @@ -234,15 +233,18 @@ public class FormatChangedTextUtil { @NotNull public static List getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) throws FilesTooBigForDiffException { - List cachedChangedLines = getCachedChangedLines(project, file); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + if (document == null) return ContainerUtil.emptyList(); + + List cachedChangedLines = getCachedChangedLines(project, document); if (cachedChangedLines != null) { return cachedChangedLines; } if (ApplicationManager.getApplication().isUnitTestMode()) { - String testContent = file.getUserData(TEST_REVISION_CONTENT); + CharSequence testContent = file.getUserData(TEST_REVISION_CONTENT); if (testContent != null) { - return calculateChangedTextRanges(file.getProject(), file, testContent); + return calculateChangedTextRanges(document, testContent); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index f8ae0ac7869e..a2371e080ffb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -47,25 +47,13 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); } - public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel model) { - super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); - mySelectionModel = model; - } - - public RearrangeCodeProcessor(@NotNull PsiFile file, - @NotNull SelectionModel selectionModel) - { - super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); - public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor, @NotNull SelectionModel selectionModel) { super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT); mySelectionModel = selectionModel; } - - public RearrangeCodeProcessor(@NotNull Project project, - @NotNull PsiFile file, - @Nullable SelectionModel selectionModel) { - super(project, file, PROGRESS_TEXT, COMMAND_NAME, false); + + public RearrangeCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); mySelectionModel = selectionModel; } From a409ee2aec3c65569863d97561b204995bd0ea0d Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 15 Jan 2015 15:46:42 +0200 Subject: [PATCH 026/231] If processing single file - count changed lines after formatting and notify user after --- .../actions/AbstractLayoutCodeProcessor.java | 17 +++- .../codeInsight/actions/CodeProcessor.java | 79 ++++++++++--------- .../actions/ReformatCodeProcessor.java | 29 +++++++ 3 files changed, 88 insertions(+), 37 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 37ad0423e6a8..e340cec99862 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -55,7 +55,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; @@ -81,6 +80,12 @@ public abstract class AbstractLayoutCodeProcessor { protected AbstractLayoutCodeProcessor myPreviousCodeProcessor; private List myFilters = ContainerUtil.newArrayList(); + private List myNotificationInfo; + + public List getNotificationInfo() { + return myNotificationInfo; + } + protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText, boolean processChangedTextOnly) { this(project, (Module)null, commandName, progressText, processChangedTextOnly); } @@ -102,6 +107,7 @@ public abstract class AbstractLayoutCodeProcessor { myCommandName = commandName; myPreviousCodeProcessor = previous; myFilters = previous.myFilters; + myNotificationInfo = previous.myNotificationInfo; } protected AbstractLayoutCodeProcessor(Project project, @@ -150,6 +156,7 @@ public abstract class AbstractLayoutCodeProcessor { myCommandName = commandName; myPostRunnable = null; myProcessChangedTextOnly = processChangedTextOnly; + myNotificationInfo = ContainerUtil.newArrayList(); } protected AbstractLayoutCodeProcessor(Project project, @@ -608,4 +615,12 @@ public abstract class AbstractLayoutCodeProcessor { notification.notify(file.getProject()); } } + + protected void addNotificationInfo(String info) { + myNotificationInfo.add(info); + } + + protected boolean isSingleFileProcessed() { + return myFile != null; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 088f9d7c77be..85ed27e699f0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -49,6 +49,8 @@ class CodeProcessor { private final PsiFile myFile; private final TextRangeType myProcessingType; + private AbstractLayoutCodeProcessor myProcessor; + public CodeProcessor(PsiFile file, Editor editor, LayoutCodeOptions runOptions) @@ -68,45 +70,44 @@ class CodeProcessor { } public void processCode() { - AbstractLayoutCodeProcessor processor = null; if (myShouldOptimizeImports) { - processor = new OptimizeImportsProcessor(myProject, myFile); + myProcessor = new OptimizeImportsProcessor(myProject, myFile); } - if (processor != null) { + if (myProcessor != null) { if (myProcessSelectedText) { - processor = new ReformatCodeProcessor(processor, myEditor.getSelectionModel()); + myProcessor = new ReformatCodeProcessor(myProcessor, myEditor.getSelectionModel()); } else { - processor = new ReformatCodeProcessor(processor, myProcessChangesTextOnly); + myProcessor = new ReformatCodeProcessor(myProcessor, myProcessChangesTextOnly); } } else { if (myProcessSelectedText) { - processor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel()); + myProcessor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel()); } else { - processor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly); + myProcessor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly); } } if (myShouldRearrangeCode) { if (myProcessSelectedText) { - processor = new RearrangeCodeProcessor(processor, myEditor.getSelectionModel()); + myProcessor = new RearrangeCodeProcessor(myProcessor, myEditor.getSelectionModel()); } else { - processor = new RearrangeCodeProcessor(processor); + myProcessor = new RearrangeCodeProcessor(myProcessor); } } if (myShouldNotify) { Document document = PsiDocumentManager.getInstance(myProject).getDocument(myFile); if (document != null) { - processor.setPostRunnable(getNotificationCallBack(document)); + myProcessor.setPostRunnable(getNotificationCallBack(document)); } } - processor.run(); + myProcessor.run(); } private Runnable getNotificationCallBack(@NotNull final Document document) { @@ -134,7 +135,7 @@ class CodeProcessor { }; } - private static int getProcessedLinesNumber(final Document document, final CharSequence before) { + protected static int getProcessedLinesNumber(final Document document, final CharSequence before) { int totalLinesProcessed = 0; try { List ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before); @@ -153,33 +154,39 @@ class CodeProcessor { @NotNull private String prepareMessage(@NotNull Document document, @NotNull CharSequence textBeforeChange) { - int totalLinesProcessed = getProcessedLinesNumber(document, textBeforeChange); + //int totalLinesProcessed = getProcessedLinesNumber(document, textBeforeChange); + // + //String linesInfo = ""; + //if (totalLinesProcessed >= 0) { + // linesInfo = "Changed " + totalLinesProcessed + " lines"; + //} + // + //String scopeInfo = myProcessingType == VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null; + //String actionsInfo = "Performed: formatting"; + //if (myShouldOptimizeImports) { + // actionsInfo += ", import optimization"; + //} + //if (myShouldRearrangeCode) { + // actionsInfo += " and code rearrangement"; + //} + // + //String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); + // + //String info = linesInfo; + //if (scopeInfo != null) { + // info += scopeInfo; + //} + //info += "\n"; + //info += actionsInfo + "\n"; + //info += shortcutInfo; - String linesInfo = ""; - if (totalLinesProcessed >= 0) { - linesInfo = "Changed " + totalLinesProcessed + " lines"; + StringBuilder builder = new StringBuilder(); + + for (String info : myProcessor.getNotificationInfo()) { + builder.append(info).append('\n'); } - String scopeInfo = myProcessingType == VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null; - String actionsInfo = "Performed: formatting"; - if (myShouldOptimizeImports) { - actionsInfo += ", import optimization"; - } - if (myShouldRearrangeCode) { - actionsInfo += " and code rearrangement"; - } - - String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); - - String info = linesInfo; - if (scopeInfo != null) { - info += scopeInfo; - } - info += "\n"; - info += actionsInfo + "\n"; - info += shortcutInfo; - - return info; + return builder.toString(); } private static void showHint(@NotNull Editor editor, @NotNull String info) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index c86255295a2a..8701961b8047 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -23,11 +23,13 @@ import com.intellij.notification.NotificationType; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.util.IncorrectOperationException; @@ -38,6 +40,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @@ -108,12 +111,27 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { throws IncorrectOperationException { return new FutureTask(new Callable() { + private Document myDocument; + @Override public Boolean call() throws Exception { FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false); try { Collection ranges = getRangesToFormat(processChangedTextOnly, file); + + CharSequence before = null; + if (isSingleFileProcessed()) { + myDocument = PsiDocumentManager.getInstance(myProject).getDocument(file); + LOG.assertTrue(myDocument != null); + before = myDocument.getImmutableCharSequence(); + } + CodeStyleManager.getInstance(myProject).reformatText(file, ranges); + + if (before != null) { + prepareUserNotificationMessage(myDocument, before); + } + return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get(); } catch (FilesTooBigForDiffException e) { @@ -131,6 +149,17 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { }); } + private void prepareUserNotificationMessage(@NotNull Document document, @NotNull CharSequence before) { + int number = CodeProcessor.getProcessedLinesNumber(document, before); + if (number > 0) { + String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); + addNotificationInfo(message); + } + else { + addNotificationInfo("formatter: no lines changed"); + } + } + @NotNull private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException { if (mySelectionModel != null) { From 90aacda1ce505848e13d9a9c11ff8bfd7f11abd0 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 15 Jan 2015 16:37:35 +0200 Subject: [PATCH 027/231] Provided marker interface for import optimizer to show feedback messages. Added messages for Java import optimizer --- .../lang/java/JavaImportOptimizer.java | 22 +++++++++++++++- .../UserNotificationInfoProvider.java | 25 +++++++++++++++++++ .../codeInsight/actions/CodeProcessor.java | 3 +++ .../actions/OptimizeImportsProcessor.java | 20 +++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java diff --git a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java index bd2d1a9a29fc..530397d76c77 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java @@ -17,6 +17,7 @@ package com.intellij.lang.java; import com.intellij.lang.ImportOptimizer; +import com.intellij.notification.UserNotificationInfoProvider; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; @@ -28,22 +29,32 @@ import com.intellij.psi.PsiJavaFile; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author max */ -public class JavaImportOptimizer implements ImportOptimizer { +public class JavaImportOptimizer implements ImportOptimizer, UserNotificationInfoProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.lang.java.JavaImportOptimizer"); + private int myImportListLengthDiff; @Override @NotNull public Runnable processFile(final PsiFile file) { + myImportListLengthDiff = 0; if (!(file instanceof PsiJavaFile)) { return EmptyRunnable.getInstance(); } Project project = file.getProject(); final PsiImportList newImportList = JavaCodeStyleManager.getInstance(project).prepareOptimizeImportsResult((PsiJavaFile)file); if (newImportList == null) return EmptyRunnable.getInstance(); + + PsiImportList oldList = ((PsiJavaFile)file).getImportList(); + if (oldList != null) { + //todo: better decision is to move calculation into runnable, since here we only plan to do things + //todo: and perform them after. Some exception may interrupt and we will see notification but nothing has happened + myImportListLengthDiff = oldList.getAllImportStatements().length - newImportList.getAllImportStatements().length; + } return new Runnable() { @Override public void run() { @@ -64,6 +75,15 @@ public class JavaImportOptimizer implements ImportOptimizer { }; } + @Nullable + @Override + public String getUserNotificationInfo() { + if (myImportListLengthDiff > 0) { + return "removed " + myImportListLengthDiff + " imports"; + } + return null; + } + @Override public boolean supports(PsiFile file) { return file instanceof PsiJavaFile; diff --git a/platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java b/platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java new file mode 100644 index 000000000000..9a0abef512a0 --- /dev/null +++ b/platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2015 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.notification; + +import org.jetbrains.annotations.Nullable; + +public interface UserNotificationInfoProvider { + + @Nullable + String getUserNotificationInfo(); + +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 85ed27e699f0..9e082de6164e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -154,6 +154,7 @@ class CodeProcessor { @NotNull private String prepareMessage(@NotNull Document document, @NotNull CharSequence textBeforeChange) { + //int totalLinesProcessed = getProcessedLinesNumber(document, textBeforeChange); // //String linesInfo = ""; @@ -187,6 +188,8 @@ class CodeProcessor { } return builder.toString(); + + } private static void showHint(@NotNull Editor editor, @NotNull String info) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index b693fb782ad7..7dbc40c9a646 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -18,7 +18,9 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.lang.ImportOptimizer; +import com.intellij.lang.Language; import com.intellij.lang.LanguageImportStatements; +import com.intellij.notification.UserNotificationInfoProvider; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.EmptyRunnable; @@ -28,6 +30,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.FutureTask; @@ -81,6 +84,9 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { } } } + + prepareUserInfoMessage(optimizers); + Runnable runnable = runnables.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() { @Override public void run() { @@ -97,4 +103,18 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { }; return new FutureTask(runnable, true); } + + private void prepareUserInfoMessage(Set optimizers) { + if (optimizers.size() == 1) { + ImportOptimizer optimizer = optimizers.iterator().next(); + if (optimizer instanceof UserNotificationInfoProvider) { + String info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); + if (info != null) { + addNotificationInfo(info); + } + return; + } + } + addNotificationInfo("imports optimized"); + } } From 09d4cce5b8a55a8f407163d2df43a43b3856d180 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 15 Jan 2015 17:07:50 +0200 Subject: [PATCH 028/231] No message if formatter changed nothing --- .../intellij/codeInsight/actions/ReformatCodeProcessor.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 8701961b8047..78c37740324a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -155,9 +155,6 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); addNotificationInfo(message); } - else { - addNotificationInfo("formatter: no lines changed"); - } } @NotNull From 0dacedacdba7fe5cc2e45f0e089cba5991c25f6c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 15 Jan 2015 17:14:51 +0200 Subject: [PATCH 029/231] Showing separate message if all processors changed nothing --- .../lang/java/JavaImportOptimizer.java | 2 +- .../codeInsight/actions/CodeProcessor.java | 80 +++++-------------- 2 files changed, 20 insertions(+), 62 deletions(-) diff --git a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java index 530397d76c77..cf487b0eca90 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java @@ -79,7 +79,7 @@ public class JavaImportOptimizer implements ImportOptimizer, UserNotificationInf @Override public String getUserNotificationInfo() { if (myImportListLengthDiff > 0) { - return "removed " + myImportListLengthDiff + " imports"; + return "removed " + myImportListLengthDiff + " import" + (myImportListLengthDiff > 1 ? "s" : ""); } return null; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 9e082de6164e..9c48176f9d03 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -101,40 +101,20 @@ class CodeProcessor { } if (myShouldNotify) { - Document document = PsiDocumentManager.getInstance(myProject).getDocument(myFile); - if (document != null) { - myProcessor.setPostRunnable(getNotificationCallBack(document)); - } + myProcessor.setPostRunnable(new Runnable() { + @Override + public void run() { + String message = prepareMessage(); + if (!myEditor.isDisposed() && myEditor.getComponent().isShowing()) { + showHint(myEditor, message); + } + } + }); } myProcessor.run(); } - private Runnable getNotificationCallBack(@NotNull final Document document) { - final CharSequence textBeforeChange = document.getImmutableCharSequence(); - final Runnable calculateChangesAndNotify = new Runnable() { - @Override - public void run() { - final String info = prepareMessage(document, textBeforeChange); - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (!myEditor.isDisposed() && myEditor.getComponent().isShowing()) { - showHint(myEditor, info); - } - } - }); - } - }; - - return new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().executeOnPooledThread(calculateChangesAndNotify); - } - }; - } - protected static int getProcessedLinesNumber(final Document document, final CharSequence before) { int totalLinesProcessed = 0; try { @@ -153,43 +133,21 @@ class CodeProcessor { } @NotNull - private String prepareMessage(@NotNull Document document, @NotNull CharSequence textBeforeChange) { - - //int totalLinesProcessed = getProcessedLinesNumber(document, textBeforeChange); - // - //String linesInfo = ""; - //if (totalLinesProcessed >= 0) { - // linesInfo = "Changed " + totalLinesProcessed + " lines"; - //} - // - //String scopeInfo = myProcessingType == VCS_CHANGED_TEXT ? ", processed only changed lines since last revision" : null; - //String actionsInfo = "Performed: formatting"; - //if (myShouldOptimizeImports) { - // actionsInfo += ", import optimization"; - //} - //if (myShouldRearrangeCode) { - // actionsInfo += " and code rearrangement"; - //} - // - //String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); - // - //String info = linesInfo; - //if (scopeInfo != null) { - // info += scopeInfo; - //} - //info += "\n"; - //info += actionsInfo + "\n"; - //info += shortcutInfo; + private String prepareMessage() { + String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); StringBuilder builder = new StringBuilder(); - - for (String info : myProcessor.getNotificationInfo()) { - builder.append(info).append('\n'); + List notifications = myProcessor.getNotificationInfo(); + if (notifications.isEmpty()) { + builder.append("code looks pretty well").append('\n'); + } else { + for (String info : notifications) { + builder.append(info).append('\n'); + } } + builder.append(shortcutInfo); return builder.toString(); - - } private static void showHint(@NotNull Editor editor, @NotNull String info) { From f706c0f3920c7fc467ec217e4fbd5b0b05f98d52 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 15:11:31 +0200 Subject: [PATCH 030/231] ArrangementEngine: now provides info, about what have been done on file --- .../arrangement/engine/ArrangementEngine.java | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java index 21d21d91e48f..10311819932c 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.codeStyle.arrangement.engine; +import com.intellij.notification.UserNotificationInfoProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -56,7 +57,17 @@ import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Se * @author Denis Zhdanov * @since 7/20/12 1:56 PM */ -public class ArrangementEngine { +public class ArrangementEngine implements UserNotificationInfoProvider { + private boolean myCodeChanged; + + @Nullable + @Override + public String getUserNotificationInfo() { + if (myCodeChanged) { + return "code rearranged"; + } + return null; + } /** * Arranges given PSI root contents that belong to the given ranges. @@ -87,8 +98,9 @@ public class ArrangementEngine { * @param file target PSI root * @param ranges target ranges to use within the given root */ - @SuppressWarnings("MethodMayBeStatic") public void arrange(@NotNull PsiFile file, @NotNull Collection ranges, @Nullable final ArrangementCallback callback) { + myCodeChanged = false; + final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); if (document == null) { return; @@ -143,7 +155,7 @@ public class ArrangementEngine { } @SuppressWarnings("unchecked") - private static void doArrange(Context context) { + private void doArrange(Context context) { // The general idea is to process entries bottom-up where every processed group belongs to the same parent. We may not bother // with entries text ranges then. We use a list and a stack for achieving that than. // @@ -363,8 +375,8 @@ public class ArrangementEngine { } @SuppressWarnings("unchecked") - private static void doArrange(@NotNull List> wrappers, - @NotNull Context context) { + private void doArrange(@NotNull List> wrappers, + @NotNull Context context) { if (wrappers.isEmpty()) { return; } @@ -408,7 +420,9 @@ public class ArrangementEngine { if (previous != null && previous.equals(previousInitial) || previous == null && previousInitial == null) { final int beforeOffset = arrangedWrapper.getStartOffset(); final int afterOffset = arrangedWrapper.getEndOffset(); - context.changer.insertSection(context, arranged.get(i), newSectionsInfo, parentWrapper, beforeOffset, afterOffset); + + boolean isInserted = context.changer.insertSection(context, arranged.get(i), newSectionsInfo, parentWrapper, beforeOffset, afterOffset); + myCodeChanged = isInserted || myCodeChanged; continue; } } @@ -416,6 +430,7 @@ public class ArrangementEngine { ArrangementEntryWrapper next = i < arranged.size() - 1 ? map.get(arranged.get(i + 1)) : null; context.changer.replace(arrangedWrapper, initialWrapper, previous, next, context); context.changer.insertSection(context, arranged.get(i), newSectionsInfo, arrangedWrapper, initialWrapper, parentWrapper); + myCodeChanged = true; } } @@ -600,7 +615,7 @@ public class ArrangementEngine { @NotNull ArrangementEntryWrapper initial, @Nullable ArrangementEntryWrapper parent); - protected abstract void insertSection(@NotNull Context context, + protected abstract boolean insertSection(@NotNull Context context, @NotNull E entry, @NotNull NewSectionInfo newSectionsInfo, @Nullable ArrangementEntryWrapper parent, int beforeOffset, int afterOffset); @@ -746,18 +761,22 @@ public class ArrangementEngine { } @Override - protected void insertSection(@NotNull Context context, + protected boolean insertSection(@NotNull Context context, @NotNull E entry, @NotNull NewSectionInfo newSectionsInfo, ArrangementEntryWrapper parent, int beforeOffset, int afterOffset) { + boolean isInserted = false; final String afterComment = newSectionsInfo.getEndComment(entry); if (afterComment != null) { insert(context, afterOffset, "\n" + afterComment); + isInserted = true; } final String beforeComment = newSectionsInfo.getStartComment(entry); if (beforeComment != null) { insert(context, beforeOffset, beforeComment + "\n"); + isInserted = true; } + return isInserted; } } @@ -886,24 +905,29 @@ public class ArrangementEngine { } @Override - protected void insertSection(@NotNull Context context, + protected boolean insertSection(@NotNull Context context, @NotNull E entry, @NotNull NewSectionInfo newSectionsInfo, @Nullable ArrangementEntryWrapper parent, int beforeOffset, int afterOffset) { + boolean isInserted = false; int diff = 0; final String afterComment = newSectionsInfo.getEndComment(entry); if (afterComment != null) { insert(context, afterOffset, "\n" + afterComment); diff += afterComment.length() + 1; + isInserted = true; } final String beforeComment = newSectionsInfo.getStartComment(entry); if (beforeComment != null) { insert(context, beforeOffset, beforeComment + "\n"); diff += beforeComment.length() + 1; + isInserted = true; } updateAllWrapperRanges(parent, diff); + + return isInserted; } /** From 218a3300386e0e94fda400ecfb1a0efd6d880cd2 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 15:25:19 +0200 Subject: [PATCH 031/231] RearrangeCodeProcessor: removed unnecessary helper class --- .../actions/RearrangeCodeProcessor.java | 70 ++++++------------- 1 file changed, 23 insertions(+), 47 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index a2371e080ffb..de52c39766f9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -76,10 +76,19 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public Boolean call() throws Exception { try { Collection ranges = getRangesToFormat(file, processChangedTextOnly); - RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME, ranges); - if (rearranger.couldRearrange()) { - rearranger.run(); + Document document = PsiDocumentManager.getInstance(myProject).getDocument(file); + + if (document != null && Rearranger.EXTENSION.forLanguage(file.getLanguage()) != null) { + Runnable command = prepareRearrangeCommand(file, ranges); + PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(document); + try { + CommandProcessor.getInstance().executeCommand(myProject, command, COMMAND_NAME, null); + } + finally { + PsiDocumentManager.getInstance(myProject).commitDocument(document); + } } + return true; } catch (FilesTooBigForDiffException e) { @@ -90,6 +99,17 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { }); } + @NotNull + private Runnable prepareRearrangeCommand(@NotNull final PsiFile file, @NotNull final Collection ranges) { + final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class); + return new Runnable() { + @Override + public void run() { + engine.arrange(file, ranges); + } + }; + } + public Collection getRangesToFormat(@NotNull PsiFile file, boolean processChangedTextOnly) throws FilesTooBigForDiffException { if (mySelectionModel != null) { return getSelectedRanges(mySelectionModel); @@ -102,47 +122,3 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { return ContainerUtil.newSmartList(file.getTextRange()); } } - - -class RearrangeCommand { - @NotNull private PsiFile myFile; - @NotNull private String myCommandName; - @NotNull private Project myProject; - private Document myDocument; - private Runnable myCommand; - private final Collection myRanges; - - RearrangeCommand(@NotNull Project project, @NotNull PsiFile file, @NotNull String commandName, @NotNull Collection ranges) { - myProject = project; - myFile = file; - myRanges = ranges; - myCommandName = commandName; - myDocument = PsiDocumentManager.getInstance(project).getDocument(file); - } - - boolean couldRearrange() { - return myDocument != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null; - } - - void run() { - assert myDocument != null; - prepare(); - try { - CommandProcessor.getInstance().executeCommand(myProject, myCommand, myCommandName, null); - } - finally { - PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); - } - } - - private void prepare() { - final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class); - myCommand = new Runnable() { - @Override - public void run() { - engine.arrange(myFile, myRanges); - } - }; - PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument); - } -} From c6afb297489e36ca4363ea3d82dd9116e4fdd9b2 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 15:30:50 +0200 Subject: [PATCH 032/231] RearrangeCodeProcessor passing feedback notifications now --- .../intellij/codeInsight/actions/RearrangeCodeProcessor.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index de52c39766f9..af59eed5eaaf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -106,6 +106,10 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { @Override public void run() { engine.arrange(file, ranges); + String info = engine.getUserNotificationInfo(); + if (info != null) { + addNotificationInfo(info); + } } }; } From 63f4030a89ac4616f539bb98f2cf1b2323bd43e5 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 17:39:09 +0200 Subject: [PATCH 033/231] Reformat code dialog shortcut text in notification greyed --- .../codeInsight/actions/CodeProcessor.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 9c48176f9d03..36cf1179bfce 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -19,13 +19,11 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.LightweightHint; import com.intellij.util.diff.FilesTooBigForDiffException; @@ -37,6 +35,8 @@ import java.util.List; import static com.intellij.codeInsight.actions.TextRangeType.*; class CodeProcessor { + private static final String COLOR = "#7D7D7D"; + private final Editor myEditor; private final boolean myShouldOptimizeImports; @@ -134,18 +134,23 @@ class CodeProcessor { @NotNull private String prepareMessage() { - String shortcutInfo = "Show reformat dialog: " + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); - StringBuilder builder = new StringBuilder(); + StringBuilder builder = new StringBuilder(""); List notifications = myProcessor.getNotificationInfo(); if (notifications.isEmpty()) { - builder.append("code looks pretty well").append('\n'); + builder.append("code looks pretty well").append("
"); } else { for (String info : notifications) { - builder.append(info).append('\n'); + builder.append(info).append("
"); } } - builder.append(shortcutInfo); + + String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); + builder.append("") + .append("Show reformat dialog: ") + .append(shortcutText) + .append("") + .append(""); return builder.toString(); } From 240fc6138d545c92d5290366139b860d4a8a6345 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 19:09:12 +0200 Subject: [PATCH 034/231] Corrected notification presentation --- .../actions/AbstractLayoutCodeProcessor.java | 14 +++-- .../codeInsight/actions/CodeProcessor.java | 39 ++++++++++++-- .../actions/LayoutCodeNotification.java | 53 +++++++++++++++++++ .../actions/OptimizeImportsProcessor.java | 9 ++-- .../actions/RearrangeCodeProcessor.java | 4 +- .../actions/ReformatCodeProcessor.java | 4 +- 6 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index e340cec99862..6b7e769fec1f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -57,6 +57,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -80,11 +81,7 @@ public abstract class AbstractLayoutCodeProcessor { protected AbstractLayoutCodeProcessor myPreviousCodeProcessor; private List myFilters = ContainerUtil.newArrayList(); - private List myNotificationInfo; - - public List getNotificationInfo() { - return myNotificationInfo; - } + private LayoutCodeNotification myNotificationInfo; protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText, boolean processChangedTextOnly) { this(project, (Module)null, commandName, progressText, processChangedTextOnly); @@ -156,7 +153,7 @@ public abstract class AbstractLayoutCodeProcessor { myCommandName = commandName; myPostRunnable = null; myProcessChangedTextOnly = processChangedTextOnly; - myNotificationInfo = ContainerUtil.newArrayList(); + myNotificationInfo = new LayoutCodeNotification(); } protected AbstractLayoutCodeProcessor(Project project, @@ -616,8 +613,9 @@ public abstract class AbstractLayoutCodeProcessor { } } - protected void addNotificationInfo(String info) { - myNotificationInfo.add(info); + @Nullable + public LayoutCodeNotification getNotificationInfo() { + return myNotificationInfo; } protected boolean isSingleFileProcessed() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 36cf1179bfce..83b28a185e4c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -19,14 +19,17 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import com.intellij.ui.LightweightHint; import com.intellij.util.diff.FilesTooBigForDiffException; +import com.intellij.util.indexing.DebugAssertions; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -35,6 +38,7 @@ import java.util.List; import static com.intellij.codeInsight.actions.TextRangeType.*; class CodeProcessor { + private static final Logger LOG = Logger.getInstance(CodeProcessor.class); private static final String COLOR = "#7D7D7D"; private final Editor myEditor; @@ -134,14 +138,29 @@ class CodeProcessor { @NotNull private String prepareMessage() { - StringBuilder builder = new StringBuilder(""); - List notifications = myProcessor.getNotificationInfo(); + LayoutCodeNotification notifications = myProcessor.getNotificationInfo(); + LOG.assertTrue(notifications != null); + if (notifications.isEmpty()) { - builder.append("code looks pretty well").append("
"); + builder.append("Code looks pretty well").append("
"); } else { - for (String info : notifications) { - builder.append(info).append("
"); + String reformatNotification = notifications.getReformatCodeNotification(); + String rearrangeNotification = notifications.getRearrangeCodeNotification(); + + if (rearrangeNotification != null || reformatNotification != null) { + String firstNotificationLine = joinAndCapitalizeFirst(reformatNotification, rearrangeNotification); + if (myProcessChangesTextOnly) { + builder.append("Processed lines, changed since last revision: "); + firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); + } + builder.append(firstNotificationLine); + builder.append("
"); + } + + String optimizeImportsNotification = notifications.getOptimizeImportsNotification(); + if (optimizeImportsNotification != null) { + builder.append(StringUtil.capitalize(optimizeImportsNotification)).append("
"); } } @@ -155,6 +174,16 @@ class CodeProcessor { return builder.toString(); } + @NotNull + private String joinAndCapitalizeFirst(String reformatNotification, String rearrangeNotification) { + String firstNotificationLine = reformatNotification != null ? reformatNotification : rearrangeNotification; + if (reformatNotification != null && rearrangeNotification != null) { + firstNotificationLine += ", " + rearrangeNotification; + } + firstNotificationLine = StringUtil.capitalize(firstNotificationLine); + return firstNotificationLine; + } + private static void showHint(@NotNull Editor editor, @NotNull String info) { JComponent component = HintUtil.createInformationLabel(info); LightweightHint hint = new LightweightHint(component); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java new file mode 100644 index 000000000000..bd06053798dd --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2015 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.codeInsight.actions; + +public class LayoutCodeNotification { + + private String optimizeImportsNotification = null; + private String reformatCodeNotification = null; + private String rearrangeCodeNotification = null; + + public String getOptimizeImportsNotification() { + return optimizeImportsNotification; + } + + public void setOptimizeImportsNotification(String optimizeImportsNotification) { + this.optimizeImportsNotification = optimizeImportsNotification; + } + + public String getReformatCodeNotification() { + return reformatCodeNotification; + } + + public void setReformatCodeNotification(String reformatCodeNotification) { + this.reformatCodeNotification = reformatCodeNotification; + } + + public String getRearrangeCodeNotification() { + return rearrangeCodeNotification; + } + + public void setRearrangeCodeNotification(String rearrangeCodeNotification) { + this.rearrangeCodeNotification = rearrangeCodeNotification; + } + + public boolean isEmpty() { + return optimizeImportsNotification == null + && rearrangeCodeNotification == null + && reformatCodeNotification == null; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index 7dbc40c9a646..dd3fa65b9f82 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -109,12 +109,15 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { ImportOptimizer optimizer = optimizers.iterator().next(); if (optimizer instanceof UserNotificationInfoProvider) { String info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); - if (info != null) { - addNotificationInfo(info); + if (info != null && getNotificationInfo() != null) { + getNotificationInfo().setOptimizeImportsNotification(info); } return; } } - addNotificationInfo("imports optimized"); + + if (getNotificationInfo() != null) { + getNotificationInfo().setOptimizeImportsNotification("imports optimized"); + } } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index af59eed5eaaf..bed0bc68ae35 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -107,8 +107,8 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public void run() { engine.arrange(file, ranges); String info = engine.getUserNotificationInfo(); - if (info != null) { - addNotificationInfo(info); + if (info != null && getNotificationInfo() != null) { + getNotificationInfo().setRearrangeCodeNotification(info); } } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 78c37740324a..32a94afc33aa 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -151,9 +151,9 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { private void prepareUserNotificationMessage(@NotNull Document document, @NotNull CharSequence before) { int number = CodeProcessor.getProcessedLinesNumber(document, before); - if (number > 0) { + if (number > 0 && getNotificationInfo() != null) { String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); - addNotificationInfo(message); + getNotificationInfo().setReformatCodeNotification(message); } } From 7d480ba10349228947dedad2c47856beeb30348e Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 19:16:31 +0200 Subject: [PATCH 035/231] CodeProcessor: extracted few methods, refactorings --- .../codeInsight/actions/CodeProcessor.java | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 83b28a185e4c..e8bcf5d46c46 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -29,8 +29,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import com.intellij.ui.LightweightHint; import com.intellij.util.diff.FilesTooBigForDiffException; -import com.intellij.util.indexing.DebugAssertions; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.List; @@ -51,7 +51,6 @@ class CodeProcessor { private final Project myProject; private final PsiFile myFile; - private final TextRangeType myProcessingType; private AbstractLayoutCodeProcessor myProcessor; @@ -63,8 +62,6 @@ class CodeProcessor { myProject = file.getProject(); myEditor = editor; - myProcessingType = runOptions.getTextRangeType(); - myShouldOptimizeImports = runOptions.isOptimizeImports(); myShouldRearrangeCode = runOptions.isRearrangeCode(); myProcessSelectedText = myEditor != null && runOptions.getTextRangeType() == SELECTED_TEXT; @@ -78,30 +75,9 @@ class CodeProcessor { myProcessor = new OptimizeImportsProcessor(myProject, myFile); } - if (myProcessor != null) { - if (myProcessSelectedText) { - myProcessor = new ReformatCodeProcessor(myProcessor, myEditor.getSelectionModel()); - } - else { - myProcessor = new ReformatCodeProcessor(myProcessor, myProcessChangesTextOnly); - } - } - else { - if (myProcessSelectedText) { - myProcessor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel()); - } - else { - myProcessor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly); - } - } - + myProcessor = mixWithReformatProcessor(myProcessor); if (myShouldRearrangeCode) { - if (myProcessSelectedText) { - myProcessor = new RearrangeCodeProcessor(myProcessor, myEditor.getSelectionModel()); - } - else { - myProcessor = new RearrangeCodeProcessor(myProcessor); - } + myProcessor = mixWithRearrangeProcessor(myProcessor); } if (myShouldNotify) { @@ -119,6 +95,37 @@ class CodeProcessor { myProcessor.run(); } + private AbstractLayoutCodeProcessor mixWithRearrangeProcessor(@NotNull AbstractLayoutCodeProcessor processor) { + if (myProcessSelectedText) { + processor = new RearrangeCodeProcessor(processor, myEditor.getSelectionModel()); + } + else { + processor = new RearrangeCodeProcessor(processor); + } + return processor; + } + + @NotNull + private AbstractLayoutCodeProcessor mixWithReformatProcessor(@Nullable AbstractLayoutCodeProcessor processor) { + if (processor != null) { + if (myProcessSelectedText) { + processor = new ReformatCodeProcessor(processor, myEditor.getSelectionModel()); + } + else { + processor = new ReformatCodeProcessor(processor, myProcessChangesTextOnly); + } + } + else { + if (myProcessSelectedText) { + processor = new ReformatCodeProcessor(myFile, myEditor.getSelectionModel()); + } + else { + processor = new ReformatCodeProcessor(myFile, myProcessChangesTextOnly); + } + } + return processor; + } + protected static int getProcessedLinesNumber(final Document document, final CharSequence before) { int totalLinesProcessed = 0; try { From 1683b51f601dc866b3463a2c26640a12ce932006 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 16 Jan 2015 19:51:54 +0200 Subject: [PATCH 036/231] Corrected messages --- .../codeInsight/actions/CodeProcessor.java | 46 +++++++++++++------ .../actions/LayoutCodeNotification.java | 5 ++ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index e8bcf5d46c46..212ac79e89ba 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -43,15 +43,17 @@ class CodeProcessor { private final Editor myEditor; + private boolean myNoChangesDetected = false; + private final boolean myProcessChangesTextOnly; + private final boolean myShouldOptimizeImports; private final boolean myShouldRearrangeCode; private final boolean myProcessSelectedText; - private final boolean myProcessChangesTextOnly; + private final boolean myShouldNotify; - private final Project myProject; - private final PsiFile myFile; + private final PsiFile myFile; private AbstractLayoutCodeProcessor myProcessor; public CodeProcessor(PsiFile file, @@ -75,6 +77,10 @@ class CodeProcessor { myProcessor = new OptimizeImportsProcessor(myProject, myFile); } + if (myProcessChangesTextOnly && !FormatChangedTextUtil.hasChanges(myFile)) { + myNoChangesDetected = true; + } + myProcessor = mixWithReformatProcessor(myProcessor); if (myShouldRearrangeCode) { myProcessor = mixWithRearrangeProcessor(myProcessor); @@ -149,20 +155,30 @@ class CodeProcessor { LayoutCodeNotification notifications = myProcessor.getNotificationInfo(); LOG.assertTrue(notifications != null); - if (notifications.isEmpty()) { - builder.append("Code looks pretty well").append("
"); - } else { - String reformatNotification = notifications.getReformatCodeNotification(); - String rearrangeNotification = notifications.getRearrangeCodeNotification(); + if (notifications.isEmpty() && !myNoChangesDetected) { + builder.append("Code processed, nothing changed").append("
"); + } + else { + if (notifications.hasReformatOrRearrangeNotification()) { + String reformatNotification = notifications.getReformatCodeNotification(); + String rearrangeNotification = notifications.getRearrangeCodeNotification(); - if (rearrangeNotification != null || reformatNotification != null) { - String firstNotificationLine = joinAndCapitalizeFirst(reformatNotification, rearrangeNotification); - if (myProcessChangesTextOnly) { - builder.append("Processed lines, changed since last revision: "); - firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); + if (rearrangeNotification != null || reformatNotification != null) { + String firstNotificationLine = joinAndCapitalizeFirst(reformatNotification, rearrangeNotification); + if (myProcessChangesTextOnly) { + builder.append("Processed lines, changed since last revision: "); + firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); + } + builder.append(firstNotificationLine); + builder.append("
"); } - builder.append(firstNotificationLine); - builder.append("
"); + } + else if (myNoChangesDetected) { + builder.append("Nothing to format"); + if (myShouldRearrangeCode) { + builder.append(" and rearrange"); + } + builder.append(", no changes since last revision").append("
"); } String optimizeImportsNotification = notifications.getOptimizeImportsNotification(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java index bd06053798dd..fa74db7a275f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java @@ -45,6 +45,11 @@ public class LayoutCodeNotification { this.rearrangeCodeNotification = rearrangeCodeNotification; } + public boolean hasReformatOrRearrangeNotification() { + return rearrangeCodeNotification != null + || reformatCodeNotification != null; + } + public boolean isEmpty() { return optimizeImportsNotification == null && rearrangeCodeNotification == null From 80b644aabaeea48ee7e4439168604d6435245d92 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 15:34:04 +0200 Subject: [PATCH 037/231] Added javadoc about message structure --- .../codeInsight/actions/CodeProcessor.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 212ac79e89ba..4aba5238f717 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -149,6 +149,36 @@ class CodeProcessor { return totalLinesProcessed; } + + /** + * Current structure: + * In general message is shown, when some processor has changed something. If it changed nothing, nothing will be shown. + * If there was not any changes at all, then we show message, why that happened. + * + * First message line, about rearrange and reformat processors(only if one if them changed something) + * Next line is shown only if there is info from one of processors: + * #info from reformat and rearrange code processors# + * + * If we process changed lines, next message is shown: + * Processed lines, changed since last revision: #info from reformat and rearrange code processors# + * + * If we process changed lines, but they are none of them, we show: + * Nothing to format, no changes since last revision + * Nothing to format and rearrange, no changes since last revision + * + * Optimize imports text + * + * Info about how to show reformat code dialog + * + * When nothing changed: + * - because reformat, optimize and rearrange changed nothing: "Code processed, changed nothing" is returned. + * - because processed are only changed lines and there was not any: + * "Nothing to format" and + * "Nothing to format and rearrange", + * depending on what we were invoking + * + * @return message to show after reformat code action invoked in editor + */ @NotNull private String prepareMessage() { StringBuilder builder = new StringBuilder(""); From b98a8d1cdf8382f70c7706a6a1a4255f0788a210 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 16:27:22 +0300 Subject: [PATCH 038/231] Messages changed --- .../com/intellij/codeInsight/actions/CodeProcessor.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 4aba5238f717..8238a2a3b028 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -186,7 +186,12 @@ class CodeProcessor { LOG.assertTrue(notifications != null); if (notifications.isEmpty() && !myNoChangesDetected) { - builder.append("Code processed, nothing changed").append("
"); + if (myProcessChangesTextOnly) { + builder.append("Changes since last revision: processed, nothing modified").append("
"); + } + else { + builder.append("Code processed, nothing modified").append("
"); + } } else { if (notifications.hasReformatOrRearrangeNotification()) { @@ -196,7 +201,7 @@ class CodeProcessor { if (rearrangeNotification != null || reformatNotification != null) { String firstNotificationLine = joinAndCapitalizeFirst(reformatNotification, rearrangeNotification); if (myProcessChangesTextOnly) { - builder.append("Processed lines, changed since last revision: "); + builder.append("Changes since last revision: "); firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); } builder.append(firstNotificationLine); From c375f802f7ca1b501ba9badd7033aa594163f86b Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 17:25:01 +0300 Subject: [PATCH 039/231] minor refactoring --- .../codeInsight/actions/CodeProcessor.java | 50 ++++--------------- 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 8238a2a3b028..0e5dcf348799 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -149,36 +149,6 @@ class CodeProcessor { return totalLinesProcessed; } - - /** - * Current structure: - * In general message is shown, when some processor has changed something. If it changed nothing, nothing will be shown. - * If there was not any changes at all, then we show message, why that happened. - * - * First message line, about rearrange and reformat processors(only if one if them changed something) - * Next line is shown only if there is info from one of processors: - * #info from reformat and rearrange code processors# - * - * If we process changed lines, next message is shown: - * Processed lines, changed since last revision: #info from reformat and rearrange code processors# - * - * If we process changed lines, but they are none of them, we show: - * Nothing to format, no changes since last revision - * Nothing to format and rearrange, no changes since last revision - * - * Optimize imports text - * - * Info about how to show reformat code dialog - * - * When nothing changed: - * - because reformat, optimize and rearrange changed nothing: "Code processed, changed nothing" is returned. - * - because processed are only changed lines and there was not any: - * "Nothing to format" and - * "Nothing to format and rearrange", - * depending on what we were invoking - * - * @return message to show after reformat code action invoked in editor - */ @NotNull private String prepareMessage() { StringBuilder builder = new StringBuilder(""); @@ -195,18 +165,16 @@ class CodeProcessor { } else { if (notifications.hasReformatOrRearrangeNotification()) { - String reformatNotification = notifications.getReformatCodeNotification(); - String rearrangeNotification = notifications.getRearrangeCodeNotification(); + String reformatInfo = notifications.getReformatCodeNotification(); + String rearrangeInfo = notifications.getRearrangeCodeNotification(); - if (rearrangeNotification != null || reformatNotification != null) { - String firstNotificationLine = joinAndCapitalizeFirst(reformatNotification, rearrangeNotification); - if (myProcessChangesTextOnly) { - builder.append("Changes since last revision: "); - firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); - } - builder.append(firstNotificationLine); - builder.append("
"); + String firstNotificationLine = joinWithCommaAndCapitalize(reformatInfo, rearrangeInfo); + if (myProcessChangesTextOnly) { + builder.append("Changes since last revision: "); + firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); } + + builder.append(firstNotificationLine).append("
"); } else if (myNoChangesDetected) { builder.append("Nothing to format"); @@ -233,7 +201,7 @@ class CodeProcessor { } @NotNull - private String joinAndCapitalizeFirst(String reformatNotification, String rearrangeNotification) { + private String joinWithCommaAndCapitalize(String reformatNotification, String rearrangeNotification) { String firstNotificationLine = reformatNotification != null ? reformatNotification : rearrangeNotification; if (reformatNotification != null && rearrangeNotification != null) { firstNotificationLine += ", " + rearrangeNotification; From 2c8a41dcf2a00d0359edc59851a607775ea09bf0 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 17:29:59 +0300 Subject: [PATCH 040/231] minor, extracted method to proper class --- .../codeInsight/actions/CodeProcessor.java | 17 ----------------- .../actions/ReformatCodeProcessor.java | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java index 0e5dcf348799..79e702d9ebd8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java @@ -132,23 +132,6 @@ class CodeProcessor { return processor; } - protected static int getProcessedLinesNumber(final Document document, final CharSequence before) { - int totalLinesProcessed = 0; - try { - List ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before); - for (TextRange range : ranges) { - int lineStartNumber = document.getLineNumber(range.getStartOffset()); - int lineEndNumber = document.getLineNumber(range.getEndOffset()); - - totalLinesProcessed += lineEndNumber - lineStartNumber + 1; - } - } - catch (FilesTooBigForDiffException e) { - return -1; - } - return totalLinesProcessed; - } - @NotNull private String prepareMessage() { StringBuilder builder = new StringBuilder(""); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 32a94afc33aa..3ec678c155ae 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -150,13 +150,30 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } private void prepareUserNotificationMessage(@NotNull Document document, @NotNull CharSequence before) { - int number = CodeProcessor.getProcessedLinesNumber(document, before); + int number = getProcessedLinesNumber(document, before); if (number > 0 && getNotificationInfo() != null) { String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); getNotificationInfo().setReformatCodeNotification(message); } } + protected static int getProcessedLinesNumber(final Document document, final CharSequence before) { + int totalLinesProcessed = 0; + try { + List ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before); + for (TextRange range : ranges) { + int lineStartNumber = document.getLineNumber(range.getStartOffset()); + int lineEndNumber = document.getLineNumber(range.getEndOffset()); + + totalLinesProcessed += lineEndNumber - lineStartNumber + 1; + } + } + catch (FilesTooBigForDiffException e) { + return -1; + } + return totalLinesProcessed; + } + @NotNull private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException { if (mySelectionModel != null) { From 114d312e4548785ad75725b5884577aa659f8abd Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 17:32:00 +0300 Subject: [PATCH 041/231] minor, renaming --- ...sorTest.java => FileInEditorProcessorTest.java} | 11 ++--------- ...deProcessor.java => FileInEditorProcessor.java} | 14 +++++--------- .../codeInsight/actions/ReformatCodeAction.java | 2 +- .../codeInsight/actions/ReformatFileAction.java | 2 +- 4 files changed, 9 insertions(+), 20 deletions(-) rename java/java-tests/testSrc/com/intellij/codeInsight/actions/{MultiActionCodeProcessorTest.java => FileInEditorProcessorTest.java} (88%) rename platform/lang-impl/src/com/intellij/codeInsight/actions/{CodeProcessor.java => FileInEditorProcessor.java} (94%) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/FileInEditorProcessorTest.java similarity index 88% rename from java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java rename to java/java-tests/testSrc/com/intellij/codeInsight/actions/FileInEditorProcessorTest.java index d43731e93b83..19ce977320d3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/MultiActionCodeProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/FileInEditorProcessorTest.java @@ -16,20 +16,13 @@ package com.intellij.codeInsight.actions; import com.intellij.JavaTestUtil; -import com.intellij.openapi.editor.Caret; -import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; - -import java.util.List; import static com.intellij.codeInsight.actions.TextRangeType.*; -public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtureTestCase { +public class FileInEditorProcessorTest extends LightPlatformCodeInsightFixtureTestCase { @Override protected String getTestDataPath() { @@ -56,7 +49,7 @@ public class MultiActionCodeProcessorTest extends LightPlatformCodeInsightFixtur myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, revisionContent); } - CodeProcessor processor = new CodeProcessor(myFixture.getFile(), myFixture.getEditor(), options); + FileInEditorProcessor processor = new FileInEditorProcessor(myFixture.getFile(), myFixture.getEditor(), options); processor.processCode(); myFixture.checkResultByFile(getTestName(true) + "_after.java"); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java similarity index 94% rename from platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java rename to platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index 79e702d9ebd8..d31fb9d2d534 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/CodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -20,25 +20,21 @@ import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import com.intellij.ui.LightweightHint; -import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.List; import static com.intellij.codeInsight.actions.TextRangeType.*; -class CodeProcessor { - private static final Logger LOG = Logger.getInstance(CodeProcessor.class); +class FileInEditorProcessor { + private static final Logger LOG = Logger.getInstance(FileInEditorProcessor.class); private static final String COLOR = "#7D7D7D"; private final Editor myEditor; @@ -56,9 +52,9 @@ class CodeProcessor { private final PsiFile myFile; private AbstractLayoutCodeProcessor myProcessor; - public CodeProcessor(PsiFile file, - Editor editor, - LayoutCodeOptions runOptions) + public FileInEditorProcessor(PsiFile file, + Editor editor, + LayoutCodeOptions runOptions) { myFile = file; myProject = file.getProject(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index f983511275ae..758cc7ac7a19 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -152,7 +152,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { } currentRunOptions.setProcessingScope(processingScope); - new CodeProcessor(file, editor, currentRunOptions).processCode(); + new FileInEditorProcessor(file, editor, currentRunOptions).processCode(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java index aace3283c4b4..2855b205e5e3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java @@ -71,7 +71,7 @@ public class ReformatFileAction extends AnAction implements DumbAware { dialog.show(); if (dialog.isOK()) { - new CodeProcessor(file, editor, dialog.getRunOptions()).processCode(); + new FileInEditorProcessor(file, editor, dialog.getRunOptions()).processCode(); } } } From 275867f90a259a46ccc847fa14d6c17b12b070e5 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 18:31:31 +0300 Subject: [PATCH 042/231] minor refactoring, extracted method for controlling info collecting behaviour --- .../actions/AbstractLayoutCodeProcessor.java | 18 ++++++++---------- .../actions/FileInEditorProcessor.java | 11 +++++------ ...ation.java => LayoutCodeInfoCollector.java} | 2 +- .../actions/OptimizeImportsProcessor.java | 12 ++++-------- .../actions/RearrangeCodeProcessor.java | 6 +++--- .../actions/ReformatCodeProcessor.java | 11 ++++------- 6 files changed, 25 insertions(+), 35 deletions(-) rename platform/lang-impl/src/com/intellij/codeInsight/actions/{LayoutCodeNotification.java => LayoutCodeInfoCollector.java} (97%) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 6b7e769fec1f..3b0a95ff666c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -57,7 +57,6 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -81,7 +80,7 @@ public abstract class AbstractLayoutCodeProcessor { protected AbstractLayoutCodeProcessor myPreviousCodeProcessor; private List myFilters = ContainerUtil.newArrayList(); - private LayoutCodeNotification myNotificationInfo; + private LayoutCodeInfoCollector myInfoCollector; protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText, boolean processChangedTextOnly) { this(project, (Module)null, commandName, progressText, processChangedTextOnly); @@ -104,7 +103,7 @@ public abstract class AbstractLayoutCodeProcessor { myCommandName = commandName; myPreviousCodeProcessor = previous; myFilters = previous.myFilters; - myNotificationInfo = previous.myNotificationInfo; + myInfoCollector = previous.myInfoCollector; } protected AbstractLayoutCodeProcessor(Project project, @@ -153,7 +152,6 @@ public abstract class AbstractLayoutCodeProcessor { myCommandName = commandName; myPostRunnable = null; myProcessChangedTextOnly = processChangedTextOnly; - myNotificationInfo = new LayoutCodeNotification(); } protected AbstractLayoutCodeProcessor(Project project, @@ -191,6 +189,10 @@ public abstract class AbstractLayoutCodeProcessor { : null; } + public void setCollectInfo(boolean isCollectInfo) { + myInfoCollector = isCollectInfo ? new LayoutCodeInfoCollector() : null; + } + public void addFileFilter(@NotNull FileFilter filter) { myFilters.add(filter); } @@ -614,11 +616,7 @@ public abstract class AbstractLayoutCodeProcessor { } @Nullable - public LayoutCodeNotification getNotificationInfo() { - return myNotificationInfo; - } - - protected boolean isSingleFileProcessed() { - return myFile != null; + public LayoutCodeInfoCollector getInfoCollector() { + return myInfoCollector; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index d31fb9d2d534..d68b56900a5a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -35,7 +35,7 @@ import static com.intellij.codeInsight.actions.TextRangeType.*; class FileInEditorProcessor { private static final Logger LOG = Logger.getInstance(FileInEditorProcessor.class); - private static final String COLOR = "#7D7D7D"; + private static final String SHORTCUT_TEXT_COLOR = "#7D7D7D"; private final Editor myEditor; @@ -83,6 +83,7 @@ class FileInEditorProcessor { } if (myShouldNotify) { + myProcessor.setCollectInfo(true); myProcessor.setPostRunnable(new Runnable() { @Override public void run() { @@ -131,7 +132,7 @@ class FileInEditorProcessor { @NotNull private String prepareMessage() { StringBuilder builder = new StringBuilder(""); - LayoutCodeNotification notifications = myProcessor.getNotificationInfo(); + LayoutCodeInfoCollector notifications = myProcessor.getInfoCollector(); LOG.assertTrue(notifications != null); if (notifications.isEmpty() && !myNoChangesDetected) { @@ -170,10 +171,8 @@ class FileInEditorProcessor { } String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); - builder.append("") - .append("Show reformat dialog: ") - .append(shortcutText) - .append("") + builder.append("") + .append("Show reformat dialog: ").append(shortcutText).append("") .append(""); return builder.toString(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeInfoCollector.java similarity index 97% rename from platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java rename to platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeInfoCollector.java index fa74db7a275f..8fc7a60d87d1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeNotification.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeInfoCollector.java @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.actions; -public class LayoutCodeNotification { +public class LayoutCodeInfoCollector { private String optimizeImportsNotification = null; private String reformatCodeNotification = null; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index dd3fa65b9f82..4f3d0c5e7f9b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.lang.ImportOptimizer; -import com.intellij.lang.Language; import com.intellij.lang.LanguageImportStatements; import com.intellij.notification.UserNotificationInfoProvider; import com.intellij.openapi.module.Module; @@ -30,7 +29,6 @@ import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.FutureTask; @@ -105,19 +103,17 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { } private void prepareUserInfoMessage(Set optimizers) { + if (getInfoCollector() == null) return; + if (optimizers.size() == 1) { ImportOptimizer optimizer = optimizers.iterator().next(); if (optimizer instanceof UserNotificationInfoProvider) { String info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); - if (info != null && getNotificationInfo() != null) { - getNotificationInfo().setOptimizeImportsNotification(info); - } + getInfoCollector().setOptimizeImportsNotification(info); return; } } - if (getNotificationInfo() != null) { - getNotificationInfo().setOptimizeImportsNotification("imports optimized"); - } + getInfoCollector().setOptimizeImportsNotification("imports optimized"); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index bed0bc68ae35..2ccbe93b04d7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -106,9 +106,9 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { @Override public void run() { engine.arrange(file, ranges); - String info = engine.getUserNotificationInfo(); - if (info != null && getNotificationInfo() != null) { - getNotificationInfo().setRearrangeCodeNotification(info); + if (getInfoCollector() != null) { + String info = engine.getUserNotificationInfo(); + getInfoCollector().setRearrangeCodeNotification(info); } } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index 3ec678c155ae..ade0b9196906 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -18,10 +18,6 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.formatting.FormattingProgressTask; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; @@ -120,7 +116,7 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { Collection ranges = getRangesToFormat(processChangedTextOnly, file); CharSequence before = null; - if (isSingleFileProcessed()) { + if (getInfoCollector() != null) { myDocument = PsiDocumentManager.getInstance(myProject).getDocument(file); LOG.assertTrue(myDocument != null); before = myDocument.getImmutableCharSequence(); @@ -150,10 +146,11 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } private void prepareUserNotificationMessage(@NotNull Document document, @NotNull CharSequence before) { + LOG.assertTrue(getInfoCollector() != null); int number = getProcessedLinesNumber(document, before); - if (number > 0 && getNotificationInfo() != null) { + if (number > 0) { String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); - getNotificationInfo().setReformatCodeNotification(message); + getInfoCollector().setReformatCodeNotification(message); } } From 4555fdd097965d75ccfdd6ed52ed2d6b4048cb18 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 19:59:05 +0300 Subject: [PATCH 043/231] Corrected notification messages --- .../codeInsight/actions/FileInEditorProcessor.java | 8 ++++---- .../codeStyle/arrangement/engine/ArrangementEngine.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index d68b56900a5a..60bc1557ec3a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -148,13 +148,13 @@ class FileInEditorProcessor { String reformatInfo = notifications.getReformatCodeNotification(); String rearrangeInfo = notifications.getRearrangeCodeNotification(); - String firstNotificationLine = joinWithCommaAndCapitalize(reformatInfo, rearrangeInfo); + builder.append(joinWithCommaAndCapitalize(reformatInfo, rearrangeInfo)); + if (myProcessChangesTextOnly) { - builder.append("Changes since last revision: "); - firstNotificationLine = StringUtil.decapitalize(firstNotificationLine); + builder.append(" in changes since last revision"); } - builder.append(firstNotificationLine).append("
"); + builder.append("
"); } else if (myNoChangesDetected) { builder.append("Nothing to format"); diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java index 10311819932c..ab461b31716f 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java @@ -64,7 +64,7 @@ public class ArrangementEngine implements UserNotificationInfoProvider { @Override public String getUserNotificationInfo() { if (myCodeChanged) { - return "code rearranged"; + return "rearranged code"; } return null; } From 04453da29144c514164093cc50ee32199c686766 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 20:48:32 +0300 Subject: [PATCH 044/231] Set all processors to collect info simultaneously --- .../codeInsight/actions/AbstractLayoutCodeProcessor.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 3b0a95ff666c..359e7e1273a2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -191,6 +191,12 @@ public abstract class AbstractLayoutCodeProcessor { public void setCollectInfo(boolean isCollectInfo) { myInfoCollector = isCollectInfo ? new LayoutCodeInfoCollector() : null; + + AbstractLayoutCodeProcessor current = this; + while (current.myPreviousCodeProcessor != null) { + current = current.myPreviousCodeProcessor; + current.myInfoCollector = myInfoCollector; + } } public void addFileFilter(@NotNull FileFilter filter) { From 29312fa3a1414b714124c7dd2127b29e6fe56be6 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 19 Jan 2015 21:10:47 +0300 Subject: [PATCH 045/231] Counting amount of deleted imports just before replacing import list --- .../lang/java/JavaImportOptimizer.java | 8 ++---- .../actions/OptimizeImportsProcessor.java | 25 ++++++++----------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java index cf487b0eca90..049477ff04fa 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java @@ -49,12 +49,6 @@ public class JavaImportOptimizer implements ImportOptimizer, UserNotificationInf final PsiImportList newImportList = JavaCodeStyleManager.getInstance(project).prepareOptimizeImportsResult((PsiJavaFile)file); if (newImportList == null) return EmptyRunnable.getInstance(); - PsiImportList oldList = ((PsiJavaFile)file).getImportList(); - if (oldList != null) { - //todo: better decision is to move calculation into runnable, since here we only plan to do things - //todo: and perform them after. Some exception may interrupt and we will see notification but nothing has happened - myImportListLengthDiff = oldList.getAllImportStatements().length - newImportList.getAllImportStatements().length; - } return new Runnable() { @Override public void run() { @@ -66,7 +60,9 @@ public class JavaImportOptimizer implements ImportOptimizer, UserNotificationInf } final PsiImportList oldImportList = ((PsiJavaFile)file).getImportList(); assert oldImportList != null; + int importsBefore = oldImportList.getAllImportStatements().length; oldImportList.replace(newImportList); + myImportListLengthDiff = importsBefore - newImportList.getAllImportStatements().length; } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index 4f3d0c5e7f9b..9e8e8d9fd5d8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -83,9 +83,9 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { } } - prepareUserInfoMessage(optimizers); + final ImportOptimizer optimizer = getInfoCollector() != null && optimizers.size() == 1 ? optimizers.iterator().next() : null; - Runnable runnable = runnables.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() { + Runnable runnable = !runnables.isEmpty() ? new Runnable() { @Override public void run() { CodeStyleManagerImpl.setSequentialProcessingAllowed(false); @@ -93,27 +93,22 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { for (Runnable runnable : runnables) { runnable.run(); } + if (optimizer != null) prepareUserInfoMessage(optimizer); } finally { CodeStyleManagerImpl.setSequentialProcessingAllowed(true); } } - }; + } : EmptyRunnable.getInstance(); return new FutureTask(runnable, true); } - private void prepareUserInfoMessage(Set optimizers) { - if (getInfoCollector() == null) return; - - if (optimizers.size() == 1) { - ImportOptimizer optimizer = optimizers.iterator().next(); - if (optimizer instanceof UserNotificationInfoProvider) { - String info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); - getInfoCollector().setOptimizeImportsNotification(info); - return; - } + private void prepareUserInfoMessage(@NotNull ImportOptimizer optimizer) { + assert getInfoCollector() != null; + String info = "imports optimized"; + if (optimizer instanceof UserNotificationInfoProvider) { + info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); } - - getInfoCollector().setOptimizeImportsNotification("imports optimized"); + getInfoCollector().setOptimizeImportsNotification(info); } } From d342beccfe4b2b908e8f1b5b85a7f073f68451a4 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 21 Jan 2015 09:41:44 +0300 Subject: [PATCH 046/231] Corrected notification messages --- .../codeInsight/actions/FileInEditorProcessor.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index 60bc1557ec3a..8b90bcc399f0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -137,10 +137,10 @@ class FileInEditorProcessor { if (notifications.isEmpty() && !myNoChangesDetected) { if (myProcessChangesTextOnly) { - builder.append("Changes since last revision: processed, nothing modified").append("
"); + builder.append("No lines changed: changes since last revision are already properly formatted").append("
"); } else { - builder.append("Code processed, nothing modified").append("
"); + builder.append("No lines changed: code is already properly formatted").append("
"); } } else { @@ -157,11 +157,7 @@ class FileInEditorProcessor { builder.append("
"); } else if (myNoChangesDetected) { - builder.append("Nothing to format"); - if (myShouldRearrangeCode) { - builder.append(" and rearrange"); - } - builder.append(", no changes since last revision").append("
"); + builder.append("No lines changed: no changes since last revision").append("
"); } String optimizeImportsNotification = notifications.getOptimizeImportsNotification(); From 2674b07b8043a7e8817942c3b8016e4551cc12e5 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 21 Jan 2015 12:36:39 +0300 Subject: [PATCH 047/231] Corrected changed lines number calculation, tests added --- .../actions/FormatChangedTextUtil.java | 41 ++++++++- .../actions/ReformatCodeProcessor.java | 19 +--- .../codeStyle/formatter/addedLines.java | 23 +++++ .../formatter/addedLines_revision.java | 7 ++ .../formatter/changedAndDeleted.java | 9 ++ .../formatter/changedAndDeleted_revision.java | 12 +++ .../formatter/changedSingleLine.java | 6 ++ .../formatter/changedSingleLine_revision.java | 6 ++ .../codeStyle/formatter/deletedLines.java | 7 ++ .../formatter/deletedLines_revision.java | 10 ++ .../testData/codeStyle/formatter/insert.java | 10 ++ .../codeStyle/formatter/insert_revision.java | 8 ++ .../codeStyle/formatter/lotsWhiteSpaces.java | 6 ++ .../formatter/lotsWhiteSpaces_revision.java | 25 +++++ .../codeStyle/formatter/modification.java | 8 ++ .../formatter/modification_revision.java | 10 ++ .../codeStyle/formatter/modifiedLines.java | 11 +++ .../formatter/modifiedLines_revision.java | 8 ++ .../actions/ChangedLinesCounterTest.java | 91 +++++++++++++++++++ 19 files changed, 297 insertions(+), 20 deletions(-) create mode 100644 platform/platform-tests/testData/codeStyle/formatter/addedLines.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/deletedLines.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/insert.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/insert_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/modification.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/modification_revision.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java create mode 100644 platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java create mode 100644 platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 2a831ed87a0a..0fe2e90f25c7 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -291,10 +291,47 @@ public class FormatChangedTextUtil { @NotNull protected static List calculateChangedTextRanges(@NotNull Document document, @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException + { + return getChangedTextRanges(document, getRanges(document, contentFromVcs)); + } + + @NotNull + private static List getRanges(@NotNull Document document, + @NotNull CharSequence contentFromVcs) throws FilesTooBigForDiffException { Document documentFromVcs = ((EditorFactoryImpl)EditorFactory.getInstance()).createDocument(contentFromVcs, true, false); - List changedRanges = new RangesBuilder(document, documentFromVcs).getRanges(); - return getChangedTextRanges(document, changedRanges); + return new RangesBuilder(document, documentFromVcs).getRanges(); + } + + protected static int calculateChangedLinesNumber(@NotNull Document document, @NotNull CharSequence contentFromVcs) { + try { + List changedRanges = getRanges(document, contentFromVcs); + int linesChanges = 0; + for (Range range : changedRanges) { + linesChanges += countLines(range); + } + return linesChanges; + } catch (FilesTooBigForDiffException e) { + LOG.info("File too big, can not calculate changed lines number"); + return -1; + } + } + + private static int countLines(Range range) { + byte rangeType = range.getType(); + if (rangeType == Range.MODIFIED) { + int currentChangedLines = range.getLine2() - range.getLine1(); + int revisionLinesChanged = range.getVcsLine2() - range.getVcsLine1(); + return Math.max(currentChangedLines, revisionLinesChanged); + } + else if (rangeType == Range.DELETED) { + return range.getVcsLine2() - range.getVcsLine1(); + } + else if (rangeType == Range.INSERTED) { + return range.getLine2() - range.getLine1(); + } + + return 0; } @NotNull diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index ade0b9196906..f7c8c8047686 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -147,30 +147,13 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { private void prepareUserNotificationMessage(@NotNull Document document, @NotNull CharSequence before) { LOG.assertTrue(getInfoCollector() != null); - int number = getProcessedLinesNumber(document, before); + int number = FormatChangedTextUtil.calculateChangedLinesNumber(document, before); if (number > 0) { String message = "formatted " + number + " line" + (number > 1 ? "s" : ""); getInfoCollector().setReformatCodeNotification(message); } } - protected static int getProcessedLinesNumber(final Document document, final CharSequence before) { - int totalLinesProcessed = 0; - try { - List ranges = FormatChangedTextUtil.calculateChangedTextRanges(document, before); - for (TextRange range : ranges) { - int lineStartNumber = document.getLineNumber(range.getStartOffset()); - int lineEndNumber = document.getLineNumber(range.getEndOffset()); - - totalLinesProcessed += lineEndNumber - lineStartNumber + 1; - } - } - catch (FilesTooBigForDiffException e) { - return -1; - } - return totalLinesProcessed; - } - @NotNull private Collection getRangesToFormat(boolean processChangedTextOnly, PsiFile file) throws FilesTooBigForDiffException { if (mySelectionModel != null) { diff --git a/platform/platform-tests/testData/codeStyle/formatter/addedLines.java b/platform/platform-tests/testData/codeStyle/formatter/addedLines.java new file mode 100644 index 000000000000..909aa3180175 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/addedLines.java @@ -0,0 +1,23 @@ +public class Add { + + public void run() { + int a = 1; + a = 2; + a = 3; + a = 4; + a = 5; + a = 6; + a = 7; + a = 8; + a = 9; + a = 10; + a = 11; + a = 12; + a = 13; + a = 14; + a = 15; + a = 16; + a = 17; + } + +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java b/platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java new file mode 100644 index 000000000000..282dbcfeab31 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/addedLines_revision.java @@ -0,0 +1,7 @@ +public class Add { + + public void run() { + + } + +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java new file mode 100644 index 000000000000..6c39c1530e29 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted.java @@ -0,0 +1,9 @@ +public class ChangedAndDeleted { + + public void run() { + String a = "12"; + int f = 31; + int g = 33; + String b = "3"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java new file mode 100644 index 000000000000..ea11b6b07260 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedAndDeleted_revision.java @@ -0,0 +1,12 @@ +public class ChangedAndDeleted { + + public void run() { + int a = 2; + int b = 3; + int c = 4; + int d = 12; + int e = 212; + int f = 31; + int g = 33; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java new file mode 100644 index 000000000000..5433fda2e122 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine.java @@ -0,0 +1,6 @@ +public class SingleLine { + + public void run() { + String a = "1"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java new file mode 100644 index 000000000000..3fab16a816e7 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/changedSingleLine_revision.java @@ -0,0 +1,6 @@ +public class SingleLine { + + public void run() { + int a = 2; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/deletedLines.java b/platform/platform-tests/testData/codeStyle/formatter/deletedLines.java new file mode 100644 index 000000000000..4e04525f61ee --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/deletedLines.java @@ -0,0 +1,7 @@ +public class DeletedLines { + + public void run() { + int a = 1; + int e = 5; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java b/platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java new file mode 100644 index 000000000000..31f696d10c23 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/deletedLines_revision.java @@ -0,0 +1,10 @@ +public class DeletedLines { + + public void run() { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/insert.java b/platform/platform-tests/testData/codeStyle/formatter/insert.java new file mode 100644 index 000000000000..e34fddabbbc8 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/insert.java @@ -0,0 +1,10 @@ +public class Insert { + + public void run() { + int a = 1; + int b = 3; + int c = 4; + String a = "aa"; + String b = "bb"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/insert_revision.java b/platform/platform-tests/testData/codeStyle/formatter/insert_revision.java new file mode 100644 index 000000000000..34959832ab08 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/insert_revision.java @@ -0,0 +1,8 @@ +public class Insert { + + public void run() { + int a = 1; + int b = 3; + int c = 4; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java new file mode 100644 index 000000000000..e08516436124 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces.java @@ -0,0 +1,6 @@ +public class WhiteSpaces { + + public void run() { + + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java new file mode 100644 index 000000000000..30257da33a66 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/lotsWhiteSpaces_revision.java @@ -0,0 +1,25 @@ +public class WhiteSpaces { + + + + + + + + + + + + + + + + + + + + + public void run() { + + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modification.java b/platform/platform-tests/testData/codeStyle/formatter/modification.java new file mode 100644 index 000000000000..f7ebb94eb68b --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modification.java @@ -0,0 +1,8 @@ +public class Modify { + + public void run() { + int a = 1; + String ad = "s"; + int d = 6; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modification_revision.java b/platform/platform-tests/testData/codeStyle/formatter/modification_revision.java new file mode 100644 index 000000000000..647ce258cf1e --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modification_revision.java @@ -0,0 +1,10 @@ +public class Modify { + + public void run() { + int a = 1; + int b = 3; + int c = 4; + int f = 5; + int d = 6; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java new file mode 100644 index 000000000000..70fc21e037c1 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines.java @@ -0,0 +1,11 @@ +public class Modified { + + public void run() { + String a = "1"; + String b = "2"; + String c = "3"; + String d = "4"; + String e = "5"; + String f = "6"; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java new file mode 100644 index 000000000000..a4b60339bfdf --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/formatter/modifiedLines_revision.java @@ -0,0 +1,8 @@ +public class Modified { + + public void run() { + int a = 1; + int b = 2; + int c = 3; + } +} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java new file mode 100644 index 000000000000..724e1e1d502d --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ChangedLinesCounterTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2000-2015 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.codeInsight.actions; + +import com.intellij.openapi.editor.Document; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import org.junit.Assert; + +import java.io.File; + +public class ChangedLinesCounterTest extends LightPlatformCodeInsightFixtureTestCase { + + static { + PlatformTestCase.initPlatformLangPrefix(); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + + "/platform/platform-tests/testData/" + + "codeStyle/formatter/"; + } + + @Override + public void tearDown() throws Exception { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); + super.tearDown(); + } + + public void doTest(int expectedLinesChanged) { + myFixture.configureByFile(getTestName(true) + "_revision.java"); + PsiFile file = myFixture.getFile(); + CharSequence revisionContent = myFixture.getDocument(file).getCharsSequence(); + + myFixture.configureByFile(getTestName(true) + ".java"); + file = myFixture.getFile(); + Document document = myFixture.getDocument(file); + + int linesChanged = FormatChangedTextUtil.calculateChangedLinesNumber(document, revisionContent); + Assert.assertTrue(linesChanged > 0); + Assert.assertEquals(expectedLinesChanged, linesChanged); + } + + public void testAddedLines() { + doTest(17); + } + + public void testModifiedLines() { + doTest(6); + } + + public void testDeletedLines() { + doTest(3); + } + + public void testChangedSingleLine() { + doTest(1); + } + + public void testChangedAndDeleted() { + doTest(6); + } + + public void testModification() { + doTest(3); + } + + public void testInsert() { + doTest(2); + } + + public void testLotsWhiteSpaces() { + doTest(19); + } +} From 0fffb1177671fadd0bb2bf9afb02c2270c3e9230 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 12 Feb 2015 21:01:20 +0300 Subject: [PATCH 048/231] Move TaskState#asCustomTaskState to CustomTaskState --- .../src/com/intellij/tasks/CustomTaskState.java | 9 ++++++++- .../src/com/intellij/tasks/TaskRepository.java | 2 +- .../tasks-api/src/com/intellij/tasks/TaskState.java | 10 ++++------ .../jira/rest/api20alpha1/JiraRestApi20Alpha1.java | 8 ++++---- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java index cd479e90aee7..0fced6c7af52 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java @@ -61,8 +61,15 @@ public class CustomTaskState { return myId.hashCode(); } + @NotNull + public static CustomTaskState fromPredefined(@NotNull TaskState state) { + final CustomTaskState result = new CustomTaskState(state.name(), state.getPresentableName()); + result.setPredefined(true); + return result; + } + @Nullable - public TaskState asPredefinedTaskState() { + public TaskState asPredefined() { if (isPredefined()) { try { return TaskState.valueOf(getId()); diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java index 05ec1f0efbc4..c6e270fdef4e 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java @@ -180,7 +180,7 @@ public abstract class TaskRepository { return ContainerUtil.map2Set(getRepositoryType().getPossibleTaskStates(), new Function() { @Override public CustomTaskState fun(TaskState state) { - return state.asCustomTaskState(); + return CustomTaskState.fromPredefined(state); } }); } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java index 95691db49270..79c504a44a60 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskState.java @@ -18,7 +18,7 @@ package com.intellij.tasks; import org.jetbrains.annotations.NotNull; /** - * Predefined common task states used before {@link CustomTaskState} was introduced. + * Predefined common task states were used before {@link CustomTaskState} was introduced. * * @author Dmitry Avdeev */ @@ -31,16 +31,14 @@ public enum TaskState { OTHER("Other"); - String myPresentableName; + private String myPresentableName; TaskState(@NotNull String presentableName) { myPresentableName = presentableName; } @NotNull - public CustomTaskState asCustomTaskState() { - final CustomTaskState result = new CustomTaskState(name(), myPresentableName); - result.setPredefined(true); - return result; + public String getPresentableName() { + return myPresentableName; } } diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java index 0108ef688f80..77c42205f3f9 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/rest/api20alpha1/JiraRestApi20Alpha1.java @@ -36,9 +36,9 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { @Override public Set getAvailableTaskStates(@NotNull Task task) throws Exception { final HashSet result = new HashSet(); - result.add(TaskState.IN_PROGRESS.asCustomTaskState()); - result.add(TaskState.RESOLVED.asCustomTaskState()); - result.add(TaskState.REOPENED.asCustomTaskState()); + result.add(CustomTaskState.fromPredefined(TaskState.IN_PROGRESS)); + result.add(CustomTaskState.fromPredefined(TaskState.RESOLVED)); + result.add(CustomTaskState.fromPredefined(TaskState.REOPENED)); return result; } @@ -72,7 +72,7 @@ public class JiraRestApi20Alpha1 extends JiraRestApi { protected String getRequestForStateTransition(@NotNull CustomTaskState state) { // REST API of JIRA 4.x for retrieving possible transitions is very limited: we can't fetch possible resolutions and // names of transition destinations. So we have no other options than to hardcode them. - final TaskState taskState = state.asPredefinedTaskState(); + final TaskState taskState = state.asPredefined(); if (taskState != null) { switch (taskState) { case IN_PROGRESS: From 4e4a8d711bd5980fe0145e910a4312e53ecf3522 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 13 Feb 2015 18:24:09 +0300 Subject: [PATCH 049/231] First naive attempt to use TemplateKindCombo in OpenTaskDialog --- .../ide/actions/TemplateKindCombo.java | 2 +- .../tasks/actions/OpenTaskDialog.form | 71 +++++++++++----- .../tasks/actions/OpenTaskDialog.java | 83 +++++++++++++------ .../com/intellij/tasks/impl/TaskUiUtil.java | 5 +- 4 files changed, 110 insertions(+), 51 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java b/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java index 5a76d4bd52c7..46521faff6c5 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/TemplateKindCombo.java @@ -99,8 +99,8 @@ public class TemplateKindCombo extends ComboboxWithBrowseButton { } private void scrollBy(int delta) { - if (delta == 0) return; final int size = getComboBox().getModel().getSize(); + if (delta == 0 || size == 0) return; int next = getComboBox().getSelectedIndex() + delta; if (next < 0 || next >= size) { if (!UISettings.getInstance().CYCLE_SCROLLING) { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index 3f506464dc95..fd6f4f24a247 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -1,24 +1,24 @@
- + - + - + - + - + @@ -31,27 +31,12 @@ - - - - - - - - - - - - - - - - + @@ -82,7 +67,7 @@ - + @@ -130,7 +115,9 @@ - + + + @@ -143,6 +130,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index ab2eac4df5ad..1d69673faeca 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -16,6 +16,7 @@ package com.intellij.tasks.actions; +import com.intellij.ide.actions.TemplateKindCombo; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.binding.BindControl; @@ -27,6 +28,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Trinity; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.VcsTaskHandler; import com.intellij.tasks.*; @@ -34,18 +36,23 @@ import com.intellij.tasks.impl.TaskManagerImpl; import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater; import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; +import com.intellij.util.Function; +import com.intellij.util.PlatformIcons; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.Set; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.List; /** * @author Dmitry Avdeev @@ -67,8 +74,9 @@ public class OpenTaskDialog extends DialogWrapper { private JBCheckBox myCreateChangelist; private JBLabel myFromLabel; private ComboBox myBranchFrom; - private ComboBox myStateComboBox; - private JLabel myStateComboBoxLabel; + private TemplateKindCombo myStateCombo; + private JLabel myStateComboLabel; + private JBLabel myStateComboHint; private final Project myProject; private final Task myTask; @@ -88,45 +96,59 @@ public class OpenTaskDialog extends DialogWrapper { binder.bindAnnotations(this); binder.reset(); - myStateComboBox.setRenderer(new ListCellRendererWrapper() { + myStateComboLabel.setLabelFor(myStateCombo); + myStateComboHint.setIcon(PlatformIcons.UP_DOWN_ARROWS); + + final JComboBox comboBox = myStateCombo.getComboBox(); + comboBox.setPreferredSize(new Dimension(300, UIUtil.fixComboBoxHeight(comboBox.getPreferredSize().height))); + final ListCellRenderer defaultRenderer = comboBox.getRenderer(); + //noinspection GtkPreferredJComboBoxRenderer + comboBox.setRenderer(new ListCellRenderer() { @Override - public void customize(JList list, CustomTaskState value, int index, boolean selected, boolean hasFocus) { - if (value != null) { - setText(value.getPresentableName()); - } - else { - setText("-- no states available --"); + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value == null) { + return new JBLabel("-- no states available --"); } + return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } }); + // Capture correct modality state final TaskRepository repository = myTask.getRepository(); if (myTask.isIssue() && repository != null && repository.isSupported(TaskRepository.STATE_UPDATING)) { // Find out proper way to determine modality state here - new ComboBoxUpdater(myProject, "Fetching available task states...", myStateComboBox) { + new ComboBoxUpdater(myProject, "Fetching available task states...", comboBox) { @NotNull @Override - protected Set fetch(@NotNull ProgressIndicator indicator) throws Exception { - return repository.getAvailableTaskStates(myTask); + protected List fetch(@NotNull ProgressIndicator indicator) throws Exception { + return ContainerUtil + .map(repository.getAvailableTaskStates(myTask), new Function() { + @Override + public CustomStateTrinityAdapter fun(CustomTaskState state) { + return new CustomStateTrinityAdapter(state); + } + }); } @Nullable @Override - public CustomTaskState getSelectedItem() { - return repository.getPreferredOpenTaskState(); + public CustomStateTrinityAdapter getSelectedItem() { + final CustomTaskState state = repository.getPreferredOpenTaskState(); + return state != null ? new CustomStateTrinityAdapter(state) : null; } @Nullable @Override - public CustomTaskState getExtraItem() { - return DO_NOT_UPDATE_STATE; + public CustomStateTrinityAdapter getExtraItem() { + return new CustomStateTrinityAdapter(DO_NOT_UPDATE_STATE); } }.queue(); } else { - myStateComboBoxLabel.setVisible(false); - myStateComboBox.setVisible(false); + myStateComboLabel.setVisible(false); + myStateComboHint.setVisible(false); + myStateCombo.setVisible(false); } TaskManagerImpl.Config state = taskManager.getState(); @@ -204,6 +226,14 @@ public class OpenTaskDialog extends DialogWrapper { myChangelistName.setText(taskManager.getChangelistName(task)); updateFields(true); } + final JComponent contentPanel = getContentPanel(); + contentPanel.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + super.keyPressed(e); + } + }); + myStateCombo.registerUpDownHint(getPreferredFocusedComponent()); init(); } @@ -232,7 +262,7 @@ public class OpenTaskDialog extends DialogWrapper { taskManager.getState().createBranch = myCreateBranch.isSelected(); final TaskRepository repository = myTask.getRepository(); - final CustomTaskState taskState = (CustomTaskState)myStateComboBox.getSelectedItem(); + final CustomTaskState taskState = ((CustomStateTrinityAdapter)myStateCombo.getComboBox().getSelectedItem()).myState; if (repository != null && taskState != null && taskState != DO_NOT_UPDATE_STATE) { try { repository.setTaskState(myTask, taskState); @@ -309,7 +339,7 @@ public class OpenTaskDialog extends DialogWrapper { return myChangelistName; } else { - return null; + return myStateCombo.getComboBox(); } } @@ -317,7 +347,12 @@ public class OpenTaskDialog extends DialogWrapper { return myPanel; } - private void createUIComponents() { - myStateComboBox = new ComboBox(300); + private static class CustomStateTrinityAdapter extends Trinity { + final CustomTaskState myState; + + public CustomStateTrinityAdapter(@NotNull CustomTaskState state) { + super(state.getPresentableName(), null, state.getId()); + myState = state; + } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java index 5bffedf3e903..3425378cf423 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java @@ -6,7 +6,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ComboBox; import com.intellij.tasks.config.TaskRepositoryEditor; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.util.ArrayUtil; @@ -86,9 +85,9 @@ public class TaskUiUtil { * indeed a rather common task. */ public static abstract class ComboBoxUpdater extends RemoteFetchTask> { - protected final ComboBox myComboBox; + protected final JComboBox myComboBox; - public ComboBoxUpdater(@Nullable Project project, @NotNull String title, @NotNull ComboBox comboBox) { + public ComboBoxUpdater(@Nullable Project project, @NotNull String title, @NotNull JComboBox comboBox) { super(project, title, ModalityState.any()); myComboBox = comboBox; } From 142397e076267df935247c18aa074875b211221c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 16 Feb 2015 13:36:19 +0300 Subject: [PATCH 050/231] Delegate to ListCellRendererWrapper instead of plain JBLabel in ListCellRenderer --- .../src/com/intellij/tasks/actions/OpenTaskDialog.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 1d69673faeca..15b3b5e18856 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -36,6 +36,7 @@ import com.intellij.tasks.impl.TaskManagerImpl; import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater; import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.util.Function; @@ -107,7 +108,12 @@ public class OpenTaskDialog extends DialogWrapper { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (value == null) { - return new JBLabel("-- no states available --"); + return new ListCellRendererWrapper() { + @Override + public void customize(JList list, CustomStateTrinityAdapter value, int index, boolean selected, boolean hasFocus) { + setText("-- no states available --"); + } + }.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); } return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } From f85550c4853fb5770f85bea8b72c927bc84c1dd3 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 16 Feb 2015 14:41:03 +0300 Subject: [PATCH 051/231] Extract updatable combo box for issue states into standalone component --- .../tasks/actions/OpenTaskDialog.form | 18 +-- .../tasks/actions/OpenTaskDialog.java | 110 ++----------- .../intellij/tasks/impl/TaskStateCombo.java | 145 ++++++++++++++++++ 3 files changed, 166 insertions(+), 107 deletions(-) create mode 100644 plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index fd6f4f24a247..6e0f0a5863ec 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -130,7 +130,7 @@
- + @@ -138,7 +138,7 @@ - + @@ -148,23 +148,13 @@ - + - + - - - - - - - - - - diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 15b3b5e18856..4e74c1d5d5ff 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -16,44 +16,33 @@ package com.intellij.tasks.actions; -import com.intellij.ide.actions.TemplateKindCombo; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.binding.BindControl; import com.intellij.openapi.options.binding.ControlBinder; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Trinity; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.VcsTaskHandler; import com.intellij.tasks.*; import com.intellij.tasks.impl.TaskManagerImpl; -import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater; +import com.intellij.tasks.impl.TaskStateCombo; import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.ColoredListCellRenderer; -import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; -import com.intellij.util.Function; -import com.intellij.util.PlatformIcons; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.List; /** * @author Dmitry Avdeev @@ -62,8 +51,6 @@ public class OpenTaskDialog extends DialogWrapper { private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.actions.SimpleOpenTaskDialog"); private static final String START_FROM_BRANCH = "start.from.branch"; - private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); - private JPanel myPanel; @BindControl(value = "clearContext", instant = true) private JCheckBox myClearContext; @@ -75,9 +62,8 @@ public class OpenTaskDialog extends DialogWrapper { private JBCheckBox myCreateChangelist; private JBLabel myFromLabel; private ComboBox myBranchFrom; - private TemplateKindCombo myStateCombo; - private JLabel myStateComboLabel; - private JBLabel myStateComboHint; + private JLabel myTaskStateLabel; + private TaskStateCombo myTaskStateCombo; private final Project myProject; private final Task myTask; @@ -97,64 +83,10 @@ public class OpenTaskDialog extends DialogWrapper { binder.bindAnnotations(this); binder.reset(); - myStateComboLabel.setLabelFor(myStateCombo); - myStateComboHint.setIcon(PlatformIcons.UP_DOWN_ARROWS); - - final JComboBox comboBox = myStateCombo.getComboBox(); - comboBox.setPreferredSize(new Dimension(300, UIUtil.fixComboBoxHeight(comboBox.getPreferredSize().height))); - final ListCellRenderer defaultRenderer = comboBox.getRenderer(); - //noinspection GtkPreferredJComboBoxRenderer - comboBox.setRenderer(new ListCellRenderer() { - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - if (value == null) { - return new ListCellRendererWrapper() { - @Override - public void customize(JList list, CustomStateTrinityAdapter value, int index, boolean selected, boolean hasFocus) { - setText("-- no states available --"); - } - }.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); - } - return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - } - }); - - - // Capture correct modality state - final TaskRepository repository = myTask.getRepository(); - if (myTask.isIssue() && repository != null && repository.isSupported(TaskRepository.STATE_UPDATING)) { - // Find out proper way to determine modality state here - new ComboBoxUpdater(myProject, "Fetching available task states...", comboBox) { - @NotNull - @Override - protected List fetch(@NotNull ProgressIndicator indicator) throws Exception { - return ContainerUtil - .map(repository.getAvailableTaskStates(myTask), new Function() { - @Override - public CustomStateTrinityAdapter fun(CustomTaskState state) { - return new CustomStateTrinityAdapter(state); - } - }); - } - - @Nullable - @Override - public CustomStateTrinityAdapter getSelectedItem() { - final CustomTaskState state = repository.getPreferredOpenTaskState(); - return state != null ? new CustomStateTrinityAdapter(state) : null; - } - - @Nullable - @Override - public CustomStateTrinityAdapter getExtraItem() { - return new CustomStateTrinityAdapter(DO_NOT_UPDATE_STATE); - } - }.queue(); - } - else { - myStateComboLabel.setVisible(false); - myStateComboHint.setVisible(false); - myStateCombo.setVisible(false); + myTaskStateLabel.setLabelFor(myTaskStateCombo); + if (!TaskStateCombo.taskStateSupported(task)) { + myTaskStateLabel.setVisible(false); + myTaskStateCombo.setVisible(false); } TaskManagerImpl.Config state = taskManager.getState(); @@ -232,14 +164,11 @@ public class OpenTaskDialog extends DialogWrapper { myChangelistName.setText(taskManager.getChangelistName(task)); updateFields(true); } - final JComponent contentPanel = getContentPanel(); - contentPanel.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - super.keyPressed(e); - } - }); - myStateCombo.registerUpDownHint(getPreferredFocusedComponent()); + final JComponent preferredFocusedComponent = getPreferredFocusedComponent(); + if (preferredFocusedComponent != null) { + myTaskStateCombo.registerUpDownAction(preferredFocusedComponent); + } + myTaskStateCombo.scheduleUpdate(); init(); } @@ -267,9 +196,9 @@ public class OpenTaskDialog extends DialogWrapper { taskManager.getState().createChangelist = myCreateChangelist.isSelected(); taskManager.getState().createBranch = myCreateBranch.isSelected(); + final CustomTaskState taskState = myTaskStateCombo.getSelectedState(); final TaskRepository repository = myTask.getRepository(); - final CustomTaskState taskState = ((CustomStateTrinityAdapter)myStateCombo.getComboBox().getSelectedItem()).myState; - if (repository != null && taskState != null && taskState != DO_NOT_UPDATE_STATE) { + if (repository != null && taskState != null) { try { repository.setTaskState(myTask, taskState); repository.setPreferredOpenTaskState(taskState); @@ -345,7 +274,7 @@ public class OpenTaskDialog extends DialogWrapper { return myChangelistName; } else { - return myStateCombo.getComboBox(); + return myTaskStateCombo.getComboBox(); } } @@ -353,12 +282,7 @@ public class OpenTaskDialog extends DialogWrapper { return myPanel; } - private static class CustomStateTrinityAdapter extends Trinity { - final CustomTaskState myState; - - public CustomStateTrinityAdapter(@NotNull CustomTaskState state) { - super(state.getPresentableName(), null, state.getId()); - myState = state; - } + private void createUIComponents() { + myTaskStateCombo = new TaskStateCombo(myProject, myTask); } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java new file mode 100644 index 000000000000..44976c179f58 --- /dev/null +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java @@ -0,0 +1,145 @@ +package com.intellij.tasks.impl; + +import com.intellij.ide.actions.TemplateKindCombo; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Trinity; +import com.intellij.tasks.CustomTaskState; +import com.intellij.tasks.Task; +import com.intellij.tasks.TaskRepository; +import com.intellij.tasks.impl.TaskUiUtil.ComboBoxUpdater; +import com.intellij.ui.ListCellRendererWrapper; +import com.intellij.ui.components.JBLabel; +import com.intellij.util.Function; +import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Mikhail Golubev + */ +public class TaskStateCombo extends JPanel { + private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); + + public static boolean taskStateSupported(@Nullable Task task) { + if (task == null || !task.isIssue()) { + return false; + } + final TaskRepository repository = task.getRepository(); + return repository != null && repository.isSupported(TaskRepository.STATE_UPDATING); + } + + private final Project myProject; + private final Task myTask; + private final TemplateKindCombo myKindCombo = new TemplateKindCombo(); + + // For designer only + @SuppressWarnings("unused") + public TaskStateCombo() { + this(null, null); + } + + @SuppressWarnings({"GtkPreferredJComboBoxRenderer", "unchecked"}) + public TaskStateCombo(Project project, Task task) { + myProject = project; + myTask = task; + + final JBLabel hintButton = new JBLabel(); + hintButton.setIcon(PlatformIcons.UP_DOWN_ARROWS); + hintButton.setToolTipText("Pressing Up or Down arrows while in editor changes the state"); + final JComboBox comboBox = myKindCombo.getComboBox(); + comboBox.setPreferredSize(new Dimension(300, UIUtil.fixComboBoxHeight(comboBox.getPreferredSize().height))); + final ListCellRenderer defaultRenderer = comboBox.getRenderer(); + comboBox.setRenderer(new ListCellRenderer() { + @SuppressWarnings({"unchecked", "GtkPreferredJComboBoxRenderer"}) + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value == null) { + return new ListCellRendererWrapper() { + @Override + public void customize(JList list, CustomStateTrinityAdapter value, int index, boolean selected, boolean hasFocus) { + setText("-- no states available --"); + } + }.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); + } + return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); + add(myKindCombo); + add(hintButton); + } + + public boolean scheduleUpdate() { + if (myProject != null && taskStateSupported(myTask)) { + final JComboBox comboBox = myKindCombo.getComboBox(); + final TaskRepository repository = myTask.getRepository(); + assert repository != null; + new ComboBoxUpdater(myProject, "Fetching available task states...", comboBox) { + @NotNull + @Override + protected java.util.List fetch(@NotNull ProgressIndicator indicator) throws Exception { + return ContainerUtil + .map(repository.getAvailableTaskStates(myTask), new Function() { + @Override + public CustomStateTrinityAdapter fun(CustomTaskState state) { + return new CustomStateTrinityAdapter(state); + } + }); + } + + @Nullable + @Override + public CustomStateTrinityAdapter getSelectedItem() { + final CustomTaskState state = repository.getPreferredOpenTaskState(); + return state != null ? new CustomStateTrinityAdapter(state) : null; + } + + @Nullable + @Override + public CustomStateTrinityAdapter getExtraItem() { + return new CustomStateTrinityAdapter(DO_NOT_UPDATE_STATE); + } + }.queue(); + return true; + } + return false; + } + + /** + * @return {@code null} if no state is available at the moment or special "do not update" state was selected + */ + @Nullable + public CustomTaskState getSelectedState() { + final CustomStateTrinityAdapter item = (CustomStateTrinityAdapter)myKindCombo.getComboBox().getSelectedItem(); + if (item == null) { + return null; + } + final CustomTaskState state = item.myState; + return state == DO_NOT_UPDATE_STATE ? null : state; + } + + public void registerUpDownAction(@NotNull JComponent focusable) { + myKindCombo.registerUpDownHint(focusable); + } + + @NotNull + public JComboBox getComboBox() { + return myKindCombo.getComboBox(); + } + + private static class CustomStateTrinityAdapter extends Trinity { + final CustomTaskState myState; + + public CustomStateTrinityAdapter(@NotNull CustomTaskState state) { + super(state.getPresentableName(), null, state.getId()); + myState = state; + } + } +} From 60a8b566a2b623d70e701d078459d74fe6c12fe5 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 16 Feb 2015 16:13:27 +0300 Subject: [PATCH 052/231] Add debug logging in Trello to figure out the cause of NFE --- .../tasks/impl/httpclient/ResponseUtil.java | 18 +++++++++++++++--- .../tasks/trello/TrelloRepository.java | 14 ++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java index e512ff04a15b..c3fc81ec27e7 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java @@ -134,14 +134,20 @@ public class ResponseUtil { if (LOG.isDebugEnabled()) { String content = getResponseContentAsString(response); TaskUtil.prettyFormatJsonToLog(LOG, content); - return myGson.fromJson(content, myClass); + return myGson.fromJson(content, myClass); + } + else { + return myGson.fromJson(getResponseContentAsReader(response), myClass); } - return myGson.fromJson(getResponseContentAsReader(response), myClass); } catch (JsonSyntaxException e) { LOG.warn("Malformed server response", e); return null; } + catch (NumberFormatException e) { + LOG.error("NFE in response: " + getResponseContentAsString(response), e); + throw new RequestFailedException("Malformed response"); + } } } @@ -175,12 +181,18 @@ public class ResponseUtil { TaskUtil.prettyFormatJsonToLog(LOG, content); return myGson.fromJson(content, myTypeToken.getType()); } - return myGson.fromJson(getResponseContentAsReader(response), myTypeToken.getType()); + else { + return myGson.fromJson(getResponseContentAsReader(response), myTypeToken.getType()); + } } catch (JsonSyntaxException e) { LOG.warn("Malformed server response", e); return Collections.emptyList(); } + catch (NumberFormatException e) { + LOG.error("NFE in response: " + getResponseContentAsString(response), e); + throw new RequestFailedException("Malformed response"); + } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java index 5a8a0c12b728..e2cc5b078150 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java @@ -36,6 +36,7 @@ import com.intellij.tasks.trello.model.TrelloCard; import com.intellij.tasks.trello.model.TrelloList; import com.intellij.tasks.trello.model.TrelloUser; import com.intellij.util.Function; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; import org.apache.http.*; @@ -207,7 +208,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { try { final URIBuilder url = new URIBuilder(getRestApiUrl("members", "me")) .addParameter("fields", TrelloUser.REQUIRED_FIELDS); - return makeRequestAndDeserializeJsonResponse(url.build(), TrelloUser.class); + return ObjectUtils.assertNotNull(makeRequestAndDeserializeJsonResponse(url.build(), TrelloUser.class)); } catch (Exception e) { LOG.warn("Error while fetching initial user info", e); @@ -223,7 +224,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { final URIBuilder url = new URIBuilder(getRestApiUrl("boards", id)) .addParameter("fields", TrelloBoard.REQUIRED_FIELDS); try { - return makeRequestAndDeserializeJsonResponse(url.build(), TrelloBoard.class); + return ObjectUtils.assertNotNull(makeRequestAndDeserializeJsonResponse(url.build(), TrelloBoard.class)); } catch (Exception e) { LOG.warn("Error while fetching initial board info", e); @@ -236,7 +237,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { final URIBuilder url = new URIBuilder(getRestApiUrl("lists", id)) .addParameter("fields", TrelloList.REQUIRED_FIELDS); try { - return makeRequestAndDeserializeJsonResponse(url.build(), TrelloList.class); + return ObjectUtils.assertNotNull(makeRequestAndDeserializeJsonResponse(url.build(), TrelloList.class)); } catch (Exception e) { LOG.warn("Error while fetching initial list info" + id, e); @@ -337,7 +338,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { return cards; } - @NotNull + @Nullable private T executeMethod(@NotNull HttpUriRequest method, @NotNull ResponseHandler handler) throws Exception { final HttpClient client = getHttpClient(); final HttpResponse response = client.execute(method); @@ -355,10 +356,11 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { @NotNull private List makeRequestAndDeserializeJsonResponse(@NotNull URI url, @NotNull TypeToken> type) throws Exception { - return executeMethod(new HttpGet(url), new GsonMultipleObjectsDeserializer(TrelloUtil.GSON, type)); + final List result = executeMethod(new HttpGet(url), new GsonMultipleObjectsDeserializer(TrelloUtil.GSON, type)); + return ObjectUtils.assertNotNull(result); } - @NotNull + @Nullable private T makeRequestAndDeserializeJsonResponse(@NotNull URI url, @NotNull Class cls) throws Exception { return executeMethod(new HttpGet(url), new GsonSingleObjectDeserializer(TrelloUtil.GSON, cls)); } From 654a2884b0eabfeae24cb13664b71eabca775fb1 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 16 Feb 2015 16:55:43 +0300 Subject: [PATCH 053/231] Use TaskStateCombo in "Close Task" dialog as well --- .../tasks/actions/CloseTaskDialog.form | 5 +- .../tasks/actions/CloseTaskDialog.java | 78 +++++++------------ .../tasks/actions/OpenTaskDialog.form | 1 + .../tasks/actions/OpenTaskDialog.java | 11 ++- .../intellij/tasks/impl/TaskStateCombo.java | 49 +++++++++--- .../com/intellij/tasks/impl/TaskUiUtil.java | 24 ++++-- 6 files changed, 97 insertions(+), 71 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form index faa9841f61c6..7508f5a7dc34 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.form @@ -78,7 +78,6 @@ -
@@ -87,9 +86,9 @@ - + - + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java index d194a073fbd7..73d14d23435a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/CloseTaskDialog.java @@ -16,9 +16,7 @@ package com.intellij.tasks.actions; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.vcs.VcsType; import com.intellij.tasks.CustomTaskState; @@ -26,77 +24,43 @@ import com.intellij.tasks.LocalTask; import com.intellij.tasks.TaskManager; import com.intellij.tasks.TaskRepository; import com.intellij.tasks.impl.TaskManagerImpl; -import com.intellij.tasks.impl.TaskUiUtil; +import com.intellij.tasks.impl.TaskStateCombo; import com.intellij.tasks.impl.TaskUtil; -import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.Set; +import java.util.Collection; /** * @author Dmitry Avdeev */ public class CloseTaskDialog extends DialogWrapper { - private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); - + private final Project myProject; + private final LocalTask myTask; private JCheckBox myCommitChanges; private JPanel myPanel; private JLabel myTaskLabel; private JBCheckBox myMergeBranches; private JPanel myVcsPanel; - private ComboBox myStateComboBox; private JLabel myStateComboBoxLabel; + private TaskStateCombo myStateCombo; private final TaskManagerImpl myTaskManager; public CloseTaskDialog(Project project, final LocalTask task) { super(project, false); + myProject = project; + myTask = task; setTitle("Close Task"); myTaskLabel.setText(TaskUtil.getTrimmedSummary(task)); myTaskLabel.setIcon(task.getIcon()); - final TaskRepository repository = task.getRepository(); - myStateComboBox.setRenderer(new ListCellRendererWrapper() { - @Override - public void customize(JList list, CustomTaskState value, int index, boolean selected, boolean hasFocus) { - if (value != null) { - setText(value.getPresentableName()); - } - else { - setText("-- no states available --"); - } - } - }); - - // Capture correct modality state - if (task.isIssue() && repository != null && repository.isSupported(TaskRepository.STATE_UPDATING)) { - // Find out proper way to determine modality state here - new TaskUiUtil.ComboBoxUpdater(project, "Fetching available task states...", myStateComboBox) { - @NotNull - @Override - protected Set fetch(@NotNull ProgressIndicator indicator) throws Exception { - return repository.getAvailableTaskStates(task); - } - - @Nullable - @Override - public CustomTaskState getSelectedItem() { - return repository.getPreferredCloseTaskState(); - } - - @Nullable - @Override - public CustomTaskState getExtraItem() { - return DO_NOT_UPDATE_STATE; - } - }.queue(); - } - else { + myStateComboBoxLabel.setLabelFor(myStateCombo); + if (!TaskStateCombo.isStateSupportedFor(task)) { myStateComboBoxLabel.setVisible(false); - myStateComboBox.setVisible(false); + myStateCombo.setVisible(false); } myTaskManager = (TaskManagerImpl)TaskManager.getManager(project); @@ -116,6 +80,11 @@ public class CloseTaskDialog extends DialogWrapper { else { myVcsPanel.setVisible(false); } + final JComponent preferredFocusedComponent = getPreferredFocusedComponent(); + if (preferredFocusedComponent != null) { + myStateCombo.registerUpDownAction(preferredFocusedComponent); + } + myStateCombo.scheduleUpdate(); init(); } @@ -123,10 +92,15 @@ public class CloseTaskDialog extends DialogWrapper { return myPanel; } + @Nullable + @Override + public JComponent getPreferredFocusedComponent() { + return myStateCombo.getComboBox(); + } + @Nullable CustomTaskState getCloseIssueState() { - final CustomTaskState selected = (CustomTaskState)myStateComboBox.getSelectedItem(); - return selected == null || selected == DO_NOT_UPDATE_STATE ? null : selected; + return myStateCombo.getSelectedState(); } boolean isCommitChanges() { @@ -149,6 +123,12 @@ public class CloseTaskDialog extends DialogWrapper { } private void createUIComponents() { - myStateComboBox = new ComboBox(300); + myStateCombo = new TaskStateCombo(myProject, myTask) { + @Nullable + @Override + protected CustomTaskState getPreferredState(@NotNull TaskRepository repository, @NotNull Collection available) { + return repository.getPreferredCloseTaskState(); + } + }; } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index 6e0f0a5863ec..d141d4e05fc4 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -155,6 +155,7 @@ + diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 4e74c1d5d5ff..485161687d68 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -43,6 +43,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; /** * @author Dmitry Avdeev @@ -84,7 +85,7 @@ public class OpenTaskDialog extends DialogWrapper { binder.reset(); myTaskStateLabel.setLabelFor(myTaskStateCombo); - if (!TaskStateCombo.taskStateSupported(task)) { + if (!TaskStateCombo.isStateSupportedFor(task)) { myTaskStateLabel.setVisible(false); myTaskStateCombo.setVisible(false); } @@ -283,6 +284,12 @@ public class OpenTaskDialog extends DialogWrapper { } private void createUIComponents() { - myTaskStateCombo = new TaskStateCombo(myProject, myTask); + myTaskStateCombo = new TaskStateCombo(myProject, myTask) { + @Nullable + @Override + protected CustomTaskState getPreferredState(@NotNull TaskRepository repository, @NotNull Collection available) { + return repository.getPreferredOpenTaskState(); + } + }; } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java index 44976c179f58..2126eece9902 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskStateCombo.java @@ -19,14 +19,16 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.util.Collection; +import java.util.List; /** * @author Mikhail Golubev */ -public class TaskStateCombo extends JPanel { +public abstract class TaskStateCombo extends JPanel { private static final CustomTaskState DO_NOT_UPDATE_STATE = new CustomTaskState("", "-- do not update --"); - public static boolean taskStateSupported(@Nullable Task task) { + public static boolean isStateSupportedFor(@Nullable Task task) { if (task == null || !task.isIssue()) { return false; } @@ -77,27 +79,21 @@ public class TaskStateCombo extends JPanel { } public boolean scheduleUpdate() { - if (myProject != null && taskStateSupported(myTask)) { + if (myProject != null && isStateSupportedFor(myTask)) { final JComboBox comboBox = myKindCombo.getComboBox(); final TaskRepository repository = myTask.getRepository(); assert repository != null; new ComboBoxUpdater(myProject, "Fetching available task states...", comboBox) { @NotNull @Override - protected java.util.List fetch(@NotNull ProgressIndicator indicator) throws Exception { - return ContainerUtil - .map(repository.getAvailableTaskStates(myTask), new Function() { - @Override - public CustomStateTrinityAdapter fun(CustomTaskState state) { - return new CustomStateTrinityAdapter(state); - } - }); + protected List fetch(@NotNull ProgressIndicator indicator) throws Exception { + return CustomStateTrinityAdapter.wrapList(repository.getAvailableTaskStates(myTask)); } @Nullable @Override public CustomStateTrinityAdapter getSelectedItem() { - final CustomTaskState state = repository.getPreferredOpenTaskState(); + final CustomTaskState state = getPreferredState(repository, CustomStateTrinityAdapter.unwrapList(myResult)); return state != null ? new CustomStateTrinityAdapter(state) : null; } @@ -134,6 +130,15 @@ public class TaskStateCombo extends JPanel { return myKindCombo.getComboBox(); } + /** + * Determine what state should be initially selected in the list. + * @param repository task repository to communicate with + * @param available tasks states already downloaded from the repository + * @return task state to select + */ + @Nullable + protected abstract CustomTaskState getPreferredState(@NotNull TaskRepository repository, @NotNull Collection available); + private static class CustomStateTrinityAdapter extends Trinity { final CustomTaskState myState; @@ -141,5 +146,25 @@ public class TaskStateCombo extends JPanel { super(state.getPresentableName(), null, state.getId()); myState = state; } + + @NotNull + static List wrapList(@NotNull Collection states) { + return ContainerUtil.map(states, new Function() { + @Override + public CustomStateTrinityAdapter fun(CustomTaskState state) { + return new CustomStateTrinityAdapter(state); + } + }); + } + + @NotNull + static List unwrapList(@NotNull Collection wrapped) { + return ContainerUtil.map(wrapped, new Function() { + @Override + public CustomTaskState fun(CustomStateTrinityAdapter adapter) { + return adapter.myState; + } + }); + } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java index 3425378cf423..0f8e571a9e87 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUiUtil.java @@ -136,13 +136,21 @@ public class TaskUiUtil { final T selected = getSelectedItem(); if (selected != null) { - if (!selected.equals(extra) && !myResult.contains(selected) && addSelectedItemIfMissing()) { - myComboBox.addItem(selected); + if (!selected.equals(extra) && !myResult.contains(selected)) { + if (addSelectedItemIfMissing()) { + myComboBox.addItem(selected); + myComboBox.setSelectedItem(selected); + } + else { + selectFirstItem(); + } + } + else { + myComboBox.setSelectedItem(selected); } - myComboBox.setSelectedItem(selected); } - else if (myComboBox.getItemCount() > 0) { - myComboBox.setSelectedIndex(0); + else { + selectFirstItem(); } } else { @@ -150,6 +158,12 @@ public class TaskUiUtil { } } + private void selectFirstItem() { + if (myComboBox.getItemCount() > 0) { + myComboBox.setSelectedIndex(0); + } + } + protected void handleError() { myComboBox.removeAllItems(); } From f62860483c230e689966253cdfe419c386115508 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 16 Feb 2015 17:05:55 +0300 Subject: [PATCH 054/231] In "Open Task" dialog combo box for state is above checkbox "Clear current context" --- .../src/com/intellij/tasks/actions/OpenTaskDialog.form | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form index d141d4e05fc4..64b57bd9d93b 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form @@ -3,7 +3,7 @@ - + @@ -11,7 +11,7 @@ - + @@ -133,7 +133,7 @@ - + @@ -155,7 +155,6 @@ - From b8e835d6a019fb9db5ce2bef9c3899dfd798d415 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 11:27:38 +0300 Subject: [PATCH 055/231] Hardcoded color string replaced with JBColor.gray --- .../codeInsight/actions/FileInEditorProcessor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index 8b90bcc399f0..0bf0822844ce 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -25,6 +25,8 @@ import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; +import com.intellij.ui.ColorUtil; +import com.intellij.ui.JBColor; import com.intellij.ui.LightweightHint; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,7 +37,6 @@ import static com.intellij.codeInsight.actions.TextRangeType.*; class FileInEditorProcessor { private static final Logger LOG = Logger.getInstance(FileInEditorProcessor.class); - private static final String SHORTCUT_TEXT_COLOR = "#7D7D7D"; private final Editor myEditor; @@ -167,7 +168,9 @@ class FileInEditorProcessor { } String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); - builder.append("") + String color = ColorUtil.toHex(JBColor.gray); + + builder.append("") .append("Show reformat dialog: ").append(shortcutText).append("") .append(""); From 13eb6f9764dd5833392f347a8be56b8e2d412e64 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 12:10:33 +0300 Subject: [PATCH 056/231] Replaced myShouldNotify field with method, added checks for headless/unit test modes when showing notification --- .../actions/FileInEditorProcessor.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index 0bf0822844ce..33813c5a5b45 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -19,6 +19,8 @@ import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; @@ -47,7 +49,6 @@ class FileInEditorProcessor { private final boolean myShouldRearrangeCode; private final boolean myProcessSelectedText; - private final boolean myShouldNotify; private final Project myProject; private final PsiFile myFile; @@ -65,8 +66,6 @@ class FileInEditorProcessor { myShouldRearrangeCode = runOptions.isRearrangeCode(); myProcessSelectedText = myEditor != null && runOptions.getTextRangeType() == SELECTED_TEXT; myProcessChangesTextOnly = runOptions.getTextRangeType() == VCS_CHANGED_TEXT; - - myShouldNotify = myEditor != null && !myProcessSelectedText; } public void processCode() { @@ -83,7 +82,7 @@ class FileInEditorProcessor { myProcessor = mixWithRearrangeProcessor(myProcessor); } - if (myShouldNotify) { + if (shouldNotify()) { myProcessor.setCollectInfo(true); myProcessor.setPostRunnable(new Runnable() { @Override @@ -196,4 +195,12 @@ class FileInEditorProcessor { HintManager.HIDE_BY_SCROLLING, 0, false); } + + private boolean shouldNotify() { + Application application = ApplicationManager.getApplication(); + if (application.isUnitTestMode() || application.isHeadlessEnvironment()) { + return false; + } + return myEditor != null && !myProcessSelectedText; + } } From a55de878896fb9bc1fdf3454c68143a2dfe4ba7f Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 12:59:27 +0300 Subject: [PATCH 057/231] move string to bundle --- .../intellij/codeInsight/actions/OptimizeImportsAction.java | 3 +-- .../src/messages/CodeInsightBundle.properties | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java index e1d200671cdb..3f17fc67a5ec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java @@ -228,8 +228,7 @@ public class OptimizeImportsAction extends AnAction { panel.setLayout(layout); panel.add(new JLabel(myText)); - myOnlyVcsCheckBox = new JCheckBox("only VCS changed files"); - + myOnlyVcsCheckBox = new JCheckBox(CodeInsightBundle.message("process.scope.changed.files")); boolean lastRunVcsChangedTextEnabled = myLastRunOptions.getLastTextRangeType() == TextRangeType.VCS_CHANGED_TEXT; myOnlyVcsCheckBox.setEnabled(myContextHasChanges); diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index c5b0f1659aa1..9db40a2e65fd 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -7,6 +7,7 @@ reformat.directory.dialog.filters=Filters process.scope.directory=Directory ''{0}'' process.scope.project=Project ''{0}'' process.scope.module=Module ''{0}'' +process.scope.changed.files=only VCS changed files reformat.code.accept.button.text=Run process.scope.file=&File {0} reformat.option.selected.text=&Selected text From bb517275a91201556a5c61cea413a71d0ed78089 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 13:32:31 +0300 Subject: [PATCH 058/231] refactored, removed unnecessary assertion --- .../codeInsight/actions/OptimizeImportsProcessor.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index 9e8e8d9fd5d8..d0f024edf332 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -93,7 +93,10 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { for (Runnable runnable : runnables) { runnable.run(); } - if (optimizer != null) prepareUserInfoMessage(optimizer); + if (optimizer != null) { + String message = retrieveMessage(optimizer); + getInfoCollector().setOptimizeImportsNotification(message); + } } finally { CodeStyleManagerImpl.setSequentialProcessingAllowed(true); @@ -103,12 +106,11 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { return new FutureTask(runnable, true); } - private void prepareUserInfoMessage(@NotNull ImportOptimizer optimizer) { - assert getInfoCollector() != null; + private static String retrieveMessage(@NotNull ImportOptimizer optimizer) { String info = "imports optimized"; if (optimizer instanceof UserNotificationInfoProvider) { info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); } - getInfoCollector().setOptimizeImportsNotification(info); + return info; } } From 2584fb89bdda69646613091a7c37dea301736e84 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 14:18:22 +0300 Subject: [PATCH 059/231] progress text moved to resource bundle --- .../intellij/codeInsight/actions/RearrangeCodeProcessor.java | 3 ++- .../src/messages/CodeInsightBundle.properties | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index 2ccbe93b04d7..fc264cdb61cc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.actions; +import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -38,7 +39,7 @@ import java.util.concurrent.FutureTask; public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { public static final String COMMAND_NAME = "Rearrange code"; - public static final String PROGRESS_TEXT = "Rearranging code..."; + public static final String PROGRESS_TEXT = CodeInsightBundle.message("process.rearrange.code"); private static final Logger LOG = Logger.getInstance(RearrangeCodeProcessor.class); private SelectionModel mySelectionModel; diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index 9db40a2e65fd..f66905a27b66 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -26,6 +26,7 @@ progress.reformat.and.optimize.common.command.text=Reformat and Optimize Imports progress.reformat.stage.wrapping.blocks=Preparing... progress.reformat.stage.processing.blocks=Calculating changes... progress.reformat.stage.applying.changes=Storing changes... +process.rearrange.code=Rearranging code... process.reformat.code=Reformat Code process.reformat.code.before.commit=Reformat Code Before Commit process.rearrange.code.before.commit=Rearrange Code Before Commit From d772251a3f2ffafa26d794d7ccaff2560b1ff70c Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 15:34:18 +0300 Subject: [PATCH 060/231] add file to the super, without whole project will be reformatted --- .../intellij/codeInsight/actions/ReformatCodeProcessor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index f7c8c8047686..e9f80bd23fad 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -36,7 +36,6 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @@ -55,7 +54,7 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } public ReformatCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { - super(file.getProject(), COMMAND_NAME, PROGRESS_TEXT, false); + super(file.getProject(), file, COMMAND_NAME, PROGRESS_TEXT, false); mySelectionModel = selectionModel; } From 1cd91e1af2c1780415b6c9515ed336624d11665e Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 16:08:47 +0300 Subject: [PATCH 061/231] refactoring, removed interface --- .../src/com/intellij/lang/java/JavaImportOptimizer.java | 5 ++--- .../InfoCollectingImportOptimizer.java} | 6 +++--- .../codeInsight/actions/OptimizeImportsProcessor.java | 6 +++--- .../psi/codeStyle/arrangement/engine/ArrangementEngine.java | 4 +--- 4 files changed, 9 insertions(+), 12 deletions(-) rename platform/lang-api/src/com/intellij/{notification/UserNotificationInfoProvider.java => lang/InfoCollectingImportOptimizer.java} (87%) diff --git a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java index 049477ff04fa..388819312e34 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java @@ -16,8 +16,7 @@ package com.intellij.lang.java; -import com.intellij.lang.ImportOptimizer; -import com.intellij.notification.UserNotificationInfoProvider; +import com.intellij.lang.InfoCollectingImportOptimizer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; @@ -34,7 +33,7 @@ import org.jetbrains.annotations.Nullable; /** * @author max */ -public class JavaImportOptimizer implements ImportOptimizer, UserNotificationInfoProvider { +public class JavaImportOptimizer implements InfoCollectingImportOptimizer { private static final Logger LOG = Logger.getInstance("#com.intellij.lang.java.JavaImportOptimizer"); private int myImportListLengthDiff; diff --git a/platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java b/platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java similarity index 87% rename from platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java rename to platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java index 9a0abef512a0..b97c5b217ae5 100644 --- a/platform/lang-api/src/com/intellij/notification/UserNotificationInfoProvider.java +++ b/platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.notification; +package com.intellij.lang; import org.jetbrains.annotations.Nullable; -public interface UserNotificationInfoProvider { +public interface InfoCollectingImportOptimizer extends ImportOptimizer { @Nullable String getUserNotificationInfo(); -} \ No newline at end of file +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index d0f024edf332..fd187c4335dd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -18,8 +18,8 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.lang.ImportOptimizer; +import com.intellij.lang.InfoCollectingImportOptimizer; import com.intellij.lang.LanguageImportStatements; -import com.intellij.notification.UserNotificationInfoProvider; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.EmptyRunnable; @@ -108,8 +108,8 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { private static String retrieveMessage(@NotNull ImportOptimizer optimizer) { String info = "imports optimized"; - if (optimizer instanceof UserNotificationInfoProvider) { - info = ((UserNotificationInfoProvider)optimizer).getUserNotificationInfo(); + if (optimizer instanceof InfoCollectingImportOptimizer) { + info = ((InfoCollectingImportOptimizer)optimizer).getUserNotificationInfo(); } return info; } diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java index ab461b31716f..b3d39daede51 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.codeStyle.arrangement.engine; -import com.intellij.notification.UserNotificationInfoProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -57,11 +56,10 @@ import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Se * @author Denis Zhdanov * @since 7/20/12 1:56 PM */ -public class ArrangementEngine implements UserNotificationInfoProvider { +public class ArrangementEngine { private boolean myCodeChanged; @Nullable - @Override public String getUserNotificationInfo() { if (myCodeChanged) { return "rearranged code"; From 2acb2f6926cef3a2d69972a75aedee49ebe13849 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 18 Feb 2015 16:19:14 +0300 Subject: [PATCH 062/231] renamed test file --- ...orProcessorTest.java => ReformatCodeActionInEditorTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename java/java-tests/testSrc/com/intellij/codeInsight/actions/{FileInEditorProcessorTest.java => ReformatCodeActionInEditorTest.java} (97%) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/FileInEditorProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java similarity index 97% rename from java/java-tests/testSrc/com/intellij/codeInsight/actions/FileInEditorProcessorTest.java rename to java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java index 19ce977320d3..058d165c3ddf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/FileInEditorProcessorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java @@ -22,7 +22,7 @@ import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCa import static com.intellij.codeInsight.actions.TextRangeType.*; -public class FileInEditorProcessorTest extends LightPlatformCodeInsightFixtureTestCase { +public class ReformatCodeActionInEditorTest extends LightPlatformCodeInsightFixtureTestCase { @Override protected String getTestDataPath() { From 6e8b5f6cdcb96e3b5d11f08f08711cac49b82b6b Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 19 Feb 2015 17:56:51 +0300 Subject: [PATCH 063/231] Refactored way of providing notification info from ImportOptimizers: just return CollectingInfoRunnable instead of plain one. --- .../lang/java/JavaImportOptimizer.java | 28 +++++++-------- .../com/intellij/lang/ImportOptimizer.java | 8 +++++ .../lang/InfoCollectingImportOptimizer.java | 25 ------------- .../actions/OptimizeImportsProcessor.java | 35 ++++++++++++------- 4 files changed, 45 insertions(+), 51 deletions(-) delete mode 100644 platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java diff --git a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java index 388819312e34..eddd536d19fb 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaImportOptimizer.java @@ -16,7 +16,7 @@ package com.intellij.lang.java; -import com.intellij.lang.InfoCollectingImportOptimizer; +import com.intellij.lang.ImportOptimizer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; @@ -33,14 +33,12 @@ import org.jetbrains.annotations.Nullable; /** * @author max */ -public class JavaImportOptimizer implements InfoCollectingImportOptimizer { +public class JavaImportOptimizer implements ImportOptimizer { private static final Logger LOG = Logger.getInstance("#com.intellij.lang.java.JavaImportOptimizer"); - private int myImportListLengthDiff; @Override @NotNull public Runnable processFile(final PsiFile file) { - myImportListLengthDiff = 0; if (!(file instanceof PsiJavaFile)) { return EmptyRunnable.getInstance(); } @@ -48,7 +46,9 @@ public class JavaImportOptimizer implements InfoCollectingImportOptimizer { final PsiImportList newImportList = JavaCodeStyleManager.getInstance(project).prepareOptimizeImportsResult((PsiJavaFile)file); if (newImportList == null) return EmptyRunnable.getInstance(); - return new Runnable() { + return new CollectingInfoRunnable() { + private int myImportListLengthDiff = 0; + @Override public void run() { try { @@ -67,16 +67,16 @@ public class JavaImportOptimizer implements InfoCollectingImportOptimizer { LOG.error(e); } } - }; - } - @Nullable - @Override - public String getUserNotificationInfo() { - if (myImportListLengthDiff > 0) { - return "removed " + myImportListLengthDiff + " import" + (myImportListLengthDiff > 1 ? "s" : ""); - } - return null; + @Nullable + @Override + public String getUserNotificationInfo() { + if (myImportListLengthDiff > 0) { + return "removed " + myImportListLengthDiff + " import" + (myImportListLengthDiff > 1 ? "s" : ""); + } + return null; + } + }; } @Override diff --git a/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java b/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java index 2e2f12af1d0f..4aca7d3abec8 100644 --- a/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java +++ b/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java @@ -18,6 +18,7 @@ package com.intellij.lang; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Implementers of the interface encapsulate optimize imports process for the language. @@ -50,4 +51,11 @@ public interface ImportOptimizer { @NotNull Runnable processFile(PsiFile file); + /** + * In order to customize notification popup after reformat code action just return it from {@link #processFile} with proper information, + * by default "imports optimized" is shown. + */ + interface CollectingInfoRunnable extends Runnable { + @Nullable String getUserNotificationInfo(); + } } diff --git a/platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java b/platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java deleted file mode 100644 index b97c5b217ae5..000000000000 --- a/platform/lang-api/src/com/intellij/lang/InfoCollectingImportOptimizer.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2000-2015 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.lang; - -import org.jetbrains.annotations.Nullable; - -public interface InfoCollectingImportOptimizer extends ImportOptimizer { - - @Nullable - String getUserNotificationInfo(); - -} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index fd187c4335dd..51a92fde83d9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.lang.ImportOptimizer; -import com.intellij.lang.InfoCollectingImportOptimizer; import com.intellij.lang.LanguageImportStatements; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -26,6 +25,7 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -36,6 +36,7 @@ import java.util.concurrent.FutureTask; public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { private static final String PROGRESS_TEXT = CodeInsightBundle.message("progress.text.optimizing.imports"); public static final String COMMAND_NAME = CodeInsightBundle.message("process.optimize.imports"); + private List myOptimizersMessages = ContainerUtil.newSmartList(); public OptimizeImportsProcessor(Project project) { super(project, COMMAND_NAME, PROGRESS_TEXT, false); @@ -83,8 +84,6 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { } } - final ImportOptimizer optimizer = getInfoCollector() != null && optimizers.size() == 1 ? optimizers.iterator().next() : null; - Runnable runnable = !runnables.isEmpty() ? new Runnable() { @Override public void run() { @@ -92,11 +91,9 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { try { for (Runnable runnable : runnables) { runnable.run(); + retrieveAndStoreNotificationInfo(runnable); } - if (optimizer != null) { - String message = retrieveMessage(optimizer); - getInfoCollector().setOptimizeImportsNotification(message); - } + putNotificationInfoIntoCollector(); } finally { CodeStyleManagerImpl.setSequentialProcessingAllowed(true); @@ -106,11 +103,25 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { return new FutureTask(runnable, true); } - private static String retrieveMessage(@NotNull ImportOptimizer optimizer) { - String info = "imports optimized"; - if (optimizer instanceof InfoCollectingImportOptimizer) { - info = ((InfoCollectingImportOptimizer)optimizer).getUserNotificationInfo(); + private void retrieveAndStoreNotificationInfo(@NotNull Runnable runnable) { + if (runnable instanceof ImportOptimizer.CollectingInfoRunnable) { + String info = ((ImportOptimizer.CollectingInfoRunnable)runnable).getUserNotificationInfo(); + if (info != null) { + myOptimizersMessages.add(info); + } } - return info; + } + + private void putNotificationInfoIntoCollector() { + LayoutCodeInfoCollector collector = getInfoCollector(); + if (collector == null) { + return; + } + + String info = "imports optimized"; + if (myOptimizersMessages.size() == 1) { + info = myOptimizersMessages.get(0); + } + collector.setOptimizeImportsNotification(info); } } From c8e6f43fe7cabab621bfa4ed40c9f0df9a474135 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Thu, 19 Feb 2015 16:46:44 +0300 Subject: [PATCH 064/231] diff: show popup in the middle of the window make it more noticeable, as we don't know which part of viewer has user's attention --- .../diff/impl/DiffRequestProcessor.java | 35 +++++++++++++++++-- .../tools/fragmented/OnesideDiffViewer.java | 15 ++------ .../diff/tools/simple/SimpleDiffViewer.java | 14 -------- .../simple/SimpleThreesideDiffViewer.java | 10 ------ .../diff/tools/util/DiffDataKeys.java | 3 ++ .../util/PrevNextDifferenceIterable.java | 4 --- .../threeside/ThreesideTextDiffViewer.java | 11 ++++++ .../util/twoside/TwosideTextDiffViewer.java | 11 ++++++ 8 files changed, 61 insertions(+), 42 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java index 5da3e9afc46f..a8d07656c78c 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -15,6 +15,9 @@ */ package com.intellij.diff.impl; +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.hint.HintManagerImpl; +import com.intellij.codeInsight.hint.HintUtil; import com.intellij.diff.DiffContext; import com.intellij.diff.DiffManagerEx; import com.intellij.diff.DiffTool; @@ -37,15 +40,20 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.util.*; import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; +import com.intellij.ui.HintHint; +import com.intellij.ui.LightweightHint; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NonNls; @@ -624,7 +632,7 @@ public abstract class DiffRequestProcessor implements Disposable { if (myIterationState != IterationState.NEXT) { // TODO: provide "change" word in chain UserData - for tests/etc - if (iterable != null) iterable.notify("Press again to go to the next file"); + notifyMessage(e.getData(DiffDataKeys.CURRENT_EDITOR), "Press again to go to the next file", true); myIterationState = IterationState.NEXT; return; } @@ -667,7 +675,7 @@ public abstract class DiffRequestProcessor implements Disposable { if (!isNavigationEnabled() || !hasPrevChange()) return; if (myIterationState != IterationState.PREV) { - if (iterable != null) iterable.notify("Press again to go to the previous file"); + notifyMessage(e.getData(DiffDataKeys.CURRENT_EDITOR), "Press again to go to the previous file", false); myIterationState = IterationState.PREV; return; } @@ -676,6 +684,29 @@ public abstract class DiffRequestProcessor implements Disposable { } } + private void notifyMessage(@Nullable Editor editor, @NotNull String message, boolean next) { + final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); + Point point = new Point(myContentPanel.getWidth() / 2, next ? myContentPanel.getHeight() - JBUI.scale(40) : JBUI.scale(40)); + + final HintHint hintHint = new HintHint(myContentPanel, point) + .setPreferredPosition(next ? Balloon.Position.above : Balloon.Position.below) + .setAwtTooltip(true) + .setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)) + .setTextBg(HintUtil.INFORMATION_COLOR) + .setShowImmediately(true); + + if (editor == null) { + final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + hint.show(myContentPanel, point.x, point.y, owner instanceof JComponent ? (JComponent)owner : null, hintHint); + } + else { + Point editorPoint = SwingUtilities.convertPoint(myContentPanel, point, editor.getComponent()); + HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, editorPoint, HintManager.HIDE_BY_ANY_KEY | + HintManager.HIDE_BY_TEXT_CHANGE | + HintManager.HIDE_BY_SCROLLING, 0, false, hintHint); + } + } + // Iterate requests protected class MyNextChangeAction extends NextChangeAction { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java index afae77b20283..7d8bbe4d944a 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffViewer.java @@ -15,9 +15,6 @@ */ package com.intellij.diff.tools.fragmented; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.HintManagerImpl; -import com.intellij.codeInsight.hint.HintUtil; import com.intellij.diff.DiffContext; import com.intellij.diff.actions.BufferedLineIterator; import com.intellij.diff.actions.NavigationContextChecker; @@ -62,7 +59,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolder; -import com.intellij.ui.LightweightHint; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.MergingCharSequence; @@ -600,14 +596,6 @@ public class OnesideDiffViewer extends TextDiffViewerBase { // private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable { - @Override - public void notify(@NotNull String message) { - final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, myEditor, HintManager.UNDER, HintManager.HIDE_BY_ANY_KEY | - HintManager.HIDE_BY_TEXT_CHANGE | - HintManager.HIDE_BY_SCROLLING, 0, false); - } - @Override public boolean canGoNext() { List diffChanges = getDiffChanges(); @@ -811,6 +799,9 @@ public class OnesideDiffViewer extends TextDiffViewerBase { if (DiffDataKeys.PREV_NEXT_DIFFERENCE_ITERABLE.is(dataId)) { return myPrevNextDifferenceIterable; } + else if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { + return myEditor; + } else { return super.getData(dataId); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java index 3dfbf67b28eb..2fb8519cc716 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java @@ -15,9 +15,6 @@ */ package com.intellij.diff.tools.simple; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.HintManagerImpl; -import com.intellij.codeInsight.hint.HintUtil; import com.intellij.diff.DiffContext; import com.intellij.diff.actions.BufferedLineIterator; import com.intellij.diff.actions.NavigationContextChecker; @@ -57,7 +54,6 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.LightweightHint; import com.intellij.util.Function; import org.jetbrains.annotations.*; @@ -488,16 +484,6 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer { // private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable { - @Override - public void notify(@NotNull String message) { - final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, getCurrentEditor(), HintManager.UNDER, - HintManager.HIDE_BY_ANY_KEY | - HintManager.HIDE_BY_TEXT_CHANGE | - HintManager.HIDE_BY_SCROLLING, - 0, false); - } - @Override public boolean canGoNext() { if (myDiffChanges.isEmpty()) return false; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java index bee26aa522b0..69162f6c3cb8 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java @@ -403,16 +403,6 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer { // private class MyPrevNextDifferenceIterable implements PrevNextDifferenceIterable { - @Override - public void notify(@NotNull String message) { - final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message)); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, getCurrentEditor(), HintManager.UNDER, - HintManager.HIDE_BY_ANY_KEY | - HintManager.HIDE_BY_TEXT_CHANGE | - HintManager.HIDE_BY_SCROLLING, - 0, false); - } - @Override public boolean canGoNext() { if (myDiffChanges.isEmpty()) return false; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java index f4b4391b8d50..e9c274e3ace5 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffDataKeys.java @@ -19,9 +19,12 @@ import com.intellij.diff.DiffContext; import com.intellij.diff.FrameDiffTool; import com.intellij.diff.requests.DiffRequest; import com.intellij.openapi.actionSystem.DataKey; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.OpenFileDescriptor; public interface DiffDataKeys { + DataKey CURRENT_EDITOR = DataKey.create("diff_current_editor"); + DataKey DIFF_REQUEST = DataKey.create("diff_request"); DataKey DIFF_CONTEXT = DataKey.create("diff_context"); DataKey DIFF_VIEWER = DataKey.create("diff_frame_viewer"); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java b/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java index aea7a7f848ae..df9581bbda02 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/PrevNextDifferenceIterable.java @@ -15,11 +15,7 @@ */ package com.intellij.diff.tools.util; -import org.jetbrains.annotations.NotNull; - public interface PrevNextDifferenceIterable { - void notify(@NotNull String message); - boolean canGoPrev(); boolean canGoNext(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java index eeed7c6800d4..462ecddc6a72 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/threeside/ThreesideTextDiffViewer.java @@ -23,6 +23,7 @@ import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; import com.intellij.diff.requests.SimpleDiffRequest; +import com.intellij.diff.tools.util.DiffDataKeys; import com.intellij.diff.tools.util.SyncScrollSupport; import com.intellij.diff.tools.util.SyncScrollSupport.ThreesideSyncScrollSupport; import com.intellij.diff.tools.util.base.TextDiffViewerBase; @@ -48,6 +49,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.CalledInAwt; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -373,6 +375,15 @@ public abstract class ThreesideTextDiffViewer extends TextDiffViewerBase { // Helpers // + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { + return getCurrentEditor(); + } + return super.getData(dataId); + } + @NotNull protected Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider) { int width = divider.getWidth(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java index 92143d4dc18b..0e776baa4ab0 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/twoside/TwosideTextDiffViewer.java @@ -23,6 +23,7 @@ import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; +import com.intellij.diff.tools.util.DiffDataKeys; import com.intellij.diff.tools.util.SyncScrollSupport; import com.intellij.diff.tools.util.SyncScrollSupport.TwosideSyncScrollSupport; import com.intellij.diff.tools.util.base.TextDiffViewerBase; @@ -48,6 +49,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.CalledInAwt; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -404,6 +406,15 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase { // Helpers // + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) { + return getCurrentEditor(); + } + return super.getData(dataId); + } + @NotNull protected Graphics2D getDividerGraphics(@NotNull Graphics g, @NotNull Component divider) { assert myEditor1 != null && myEditor2 != null; From 36b00479f9ea6eb0d93b2d047c051a0d4f5b6c2e Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Thu, 19 Feb 2015 21:06:38 +0300 Subject: [PATCH 065/231] EA-65136 diff: fix NPE getContentTitles() contains nullable elements --- .../diff-impl/src/com/intellij/diff/util/DiffUtil.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index 591c3c976136..3f79865d3f10 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -57,6 +57,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapperDialog; import com.intellij.openapi.ui.WindowWrapper; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; @@ -78,6 +79,7 @@ import java.awt.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.BitSet; +import java.util.Collections; import java.util.List; public class DiffUtil { @@ -349,8 +351,12 @@ public class DiffUtil { List result = new ArrayList(contents.size()); + if (equalCharsets && equalSeparators && ContainerUtil.find(titles, Condition.NOT_NULL) == null) { + return Collections.nCopies(titles.size(), null); + } + for (int i = 0; i < contents.size(); i++) { - result.add(createTitle(titles.get(i), contents.get(i), equalCharsets, equalSeparators, editors.get(i))); + result.add(createTitle(StringUtil.notNullize(titles.get(i)), contents.get(i), equalCharsets, equalSeparators, editors.get(i))); } return result; From 443ffd6b1e95df334694f55195baeada01968677 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 20 Feb 2015 12:30:41 +0300 Subject: [PATCH 066/231] HiDpi default component sizes --- .../src/com/intellij/diff/tools/util/DiffSplitter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java index bbebf841a7e3..dc123ab4ecd9 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffSplitter.java @@ -17,6 +17,7 @@ package com.intellij.diff.tools.util; import com.intellij.openapi.ui.Divider; import com.intellij.openapi.ui.Splitter; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +29,7 @@ public class DiffSplitter extends Splitter { @Nullable private Painter myPainter; public DiffSplitter() { - setDividerWidth(30); + setDividerWidth(JBUI.scale(30)); } @Override From 2eb4d637f0386cf55001cb11a87006eaa85331ab Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 12:01:17 +0100 Subject: [PATCH 067/231] ensure field prefixes/suffixes are stripped on getters/setters generation (IDEA-136777) --- .../codeInsight/generation/builderSetter.vm | 2 +- .../codeInsight/generation/defaultGetter.vm | 2 +- .../codeInsight/generation/defaultSetter.vm | 2 +- .../GenerateGetterSetterTest.groovy | 31 +++++++++++++++++++ .../generate/element/GenerationHelper.java | 8 +++-- 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm b/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm index bb6bb906b464..4c1046e4f503 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/builderSetter.vm @@ -5,7 +5,7 @@ static void ## #else $classname ## #end -set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($field.name))($field.type $paramName) { +set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($field.type $paramName) { #if ($field.name == $paramName) #if (!$field.modifierStatic) this.## diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm b/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm index b63bfeb33fd8..7482fcfb2a6c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/defaultGetter.vm @@ -3,7 +3,7 @@ public ## static ## #end $field.type ## -#set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($field.name))) +#set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))) #if ($field.boolean) #if ($StringUtil.startsWithIgnoreCase($name, 'is')) #set($name = $StringUtil.decapitalize($name)) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm b/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm index 1418987baba0..7a1e2a76100e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm +++ b/java/java-impl/src/com/intellij/codeInsight/generation/defaultSetter.vm @@ -3,7 +3,7 @@ public ## #if($field.modifierStatic) static ## #end -void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($field.name))($field.type $paramName) { +void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($field.type $paramName) { #if ($field.name == $paramName) #if (!$field.modifierStatic) this.## diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy index 89213c72649f..50206caa0053 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy @@ -20,6 +20,9 @@ import com.intellij.codeInsight.generation.GenerateSetterHandler import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project +import com.intellij.psi.codeStyle.CodeStyleSettings +import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.intellij.util.ui.UIUtil import com.siyeh.ig.style.UnqualifiedFieldAccessInspection @@ -70,6 +73,34 @@ class Foo { ''' } + public void "test strip field prefix"() { + def settings = CodeStyleSettingsManager.getInstance(getProject()).currentSettings + String oldPrefix = settings.FIELD_NAME_PREFIX + try { + settings.FIELD_NAME_PREFIX = "my" + myFixture.configureByText 'a.java', ''' + class Foo { + String myName; + + + } + ''' + generateGetter() + myFixture.checkResult ''' + class Foo { + String myName; + + public String getName() { + return myName; + } + } + ''' + } + finally { + settings.FIELD_NAME_PREFIX = oldPrefix + } + } + public void "test qualified this"() { myFixture.enableInspections(UnqualifiedFieldAccessInspection.class) myFixture.configureByText 'a.java', ''' diff --git a/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java b/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java index 41ca3c2de064..758f83249519 100644 --- a/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java +++ b/plugins/generate-tostring/src/org/jetbrains/java/generate/element/GenerationHelper.java @@ -52,9 +52,13 @@ public class GenerationHelper { } public static String getParamName(FieldElement fieldElement, Project project) { + JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); + return codeStyleManager.propertyNameToVariableName(getPropertyName(fieldElement, project), VariableKind.PARAMETER); + } + + public static String getPropertyName(FieldElement fieldElement, Project project) { String name = fieldElement.getName(); JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); - String propertyName = codeStyleManager.variableNameToPropertyName(name, VariableKind.FIELD); - return codeStyleManager.propertyNameToVariableName(propertyName, VariableKind.PARAMETER); + return codeStyleManager.variableNameToPropertyName(name, VariableKind.FIELD); } } From 4b80f8009aa53a3c8a1d34456b12c5ff5ee8af1d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 12:40:11 +0100 Subject: [PATCH 068/231] disable for->foreach inspection if iterator is used in method reference qualifier (IDEA-136642) --- .../ForCanBeForeachInspectionBase.java | 79 ++++++++----------- .../migration/foreach/ForCanBeForEach.java | 14 ++++ .../ForCanBeForeachInspectionTest.java | 8 ++ 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java index 64954449458b..1991167dca8f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/ForCanBeForeachInspectionBase.java @@ -178,14 +178,12 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { return visitor.isIndexVariableUsedOnlyAsIndex(); } - static boolean isCollectionLoopStatement( - PsiForStatement forStatement, boolean ignoreUntypedCollections) { + static boolean isCollectionLoopStatement(PsiForStatement forStatement, boolean ignoreUntypedCollections) { final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return false; } - final PsiDeclarationStatement declaration = - (PsiDeclarationStatement)initialization; + final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization; final PsiElement[] declaredElements = declaration.getDeclaredElements(); if (declaredElements.length != 1) { return false; @@ -195,9 +193,7 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { return false; } final PsiVariable variable = (PsiVariable)declaredElement; - if (!TypeUtils.variableHasTypeOrSubtype(variable, - CommonClassNames.JAVA_UTIL_ITERATOR, - "java.util.ListIterator")) { + if (!TypeUtils.variableHasTypeOrSubtype(variable, CommonClassNames.JAVA_UTIL_ITERATOR, "java.util.ListIterator")) { return false; } final PsiExpression initialValue = variable.getInitializer(); @@ -207,14 +203,10 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (!(initialValue instanceof PsiMethodCallExpression)) { return false; } - final PsiMethodCallExpression initialCall = - (PsiMethodCallExpression)initialValue; - final PsiReferenceExpression initialMethodExpression = - initialCall.getMethodExpression(); - @NonNls final String initialCallName = - initialMethodExpression.getReferenceName(); - if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) && - !"listIterator".equals(initialCallName)) { + final PsiMethodCallExpression initialCall = (PsiMethodCallExpression)initialValue; + final PsiReferenceExpression initialMethodExpression = initialCall.getMethodExpression(); + @NonNls final String initialCallName = initialMethodExpression.getReferenceName(); + if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) && !"listIterator".equals(initialCallName)) { return false; } final PsiExpressionList argumentList = initialCall.getArgumentList(); @@ -222,12 +214,10 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (arguments.length != 0) { return false; } - final PsiExpression qualifier = - initialMethodExpression.getQualifierExpression(); + final PsiExpression qualifier = initialMethodExpression.getQualifierExpression(); final PsiClass qualifierClass; if (qualifier == null) { - qualifierClass = - ClassUtils.getContainingClass(initialMethodExpression); + qualifierClass = ClassUtils.getContainingClass(initialMethodExpression); if (ignoreUntypedCollections) { final PsiClassType type = (PsiClassType)variable.getType(); final PsiType[] parameters = type.getParameters(); @@ -255,10 +245,8 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (qualifierClass == null) { return false; } - if (!InheritanceUtil.isInheritor(qualifierClass, - CommonClassNames.JAVA_LANG_ITERABLE) && - !InheritanceUtil.isInheritor(qualifierClass, - CommonClassNames.JAVA_UTIL_COLLECTION)) { + if (!InheritanceUtil.isInheritor(qualifierClass, CommonClassNames.JAVA_LANG_ITERABLE) && + !InheritanceUtil.isInheritor(qualifierClass, CommonClassNames.JAVA_UTIL_COLLECTION)) { return false; } final PsiExpression condition = forStatement.getCondition(); @@ -289,16 +277,13 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (body == null) { return 0; } - final NumCallsToIteratorNextVisitor visitor = - new NumCallsToIteratorNextVisitor(iterator); + final NumCallsToIteratorNextVisitor visitor = new NumCallsToIteratorNextVisitor(iterator); body.accept(visitor); return visitor.getNumCallsToIteratorNext(); } - private static boolean isIteratorMethodCalled(PsiVariable iterator, - PsiStatement body) { - final IteratorMethodCallVisitor visitor = - new IteratorMethodCallVisitor(iterator); + private static boolean isIteratorMethodCalled(PsiVariable iterator, PsiStatement body) { + final IteratorMethodCallVisitor visitor = new IteratorMethodCallVisitor(iterator); body.accept(visitor); return visitor.isMethodCalled(); } @@ -308,29 +293,25 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { if (!(condition instanceof PsiMethodCallExpression)) { return false; } - final PsiMethodCallExpression call = - (PsiMethodCallExpression)condition; + final PsiMethodCallExpression call = (PsiMethodCallExpression)condition; final PsiExpressionList argumentList = call.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 0) { return false; } - final PsiReferenceExpression methodExpression = - call.getMethodExpression(); + final PsiReferenceExpression methodExpression = call.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (!HardcodedMethodConstants.HAS_NEXT.equals(methodName)) { return false; } - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null) { return true; } if (!(qualifier instanceof PsiReferenceExpression)) { return false; } - final PsiReferenceExpression referenceExpression = - (PsiReferenceExpression)qualifier; + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier; final PsiElement target = referenceExpression.resolve(); return iterator.equals(target); } @@ -636,31 +617,39 @@ public class ForCanBeForeachInspectionBase extends BaseInspection { } @Override - public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression) { + public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { if (methodCalled) { return; } super.visitMethodCallExpression(expression); - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String name = methodExpression.getReferenceName(); if (HardcodedMethodConstants.NEXT.equals(name)) { return; } - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiReferenceExpression)) { return; } - final PsiReferenceExpression referenceExpression = - (PsiReferenceExpression)qualifier; + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier; final PsiElement target = referenceExpression.resolve(); if (iterator.equals(target)) { methodCalled = true; } } + @Override + public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { + if (methodCalled) { + return; + } + super.visitMethodReferenceExpression(expression); + final PsiExpression qualifierExpression = expression.getQualifierExpression(); + if (qualifierExpression instanceof PsiReferenceExpression && iterator.equals(((PsiReferenceExpression)qualifierExpression).resolve())) { + methodCalled = true; + } + } + public boolean isMethodCalled() { return methodCalled; } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java index f742c291ad8a..eb06803e174a 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach/ForCanBeForEach.java @@ -273,6 +273,20 @@ public class ForCanBeForEach { } } } + + static class WithMethodRefs { + private static final List STRINGS = new ArrayList<>(Arrays.asList("Hello", "World")); + + public void test3() { + for (ListIterator stringListIterator = STRINGS.listIterator(); stringListIterator.hasNext(); ) { + System.out.println(stringListIterator.next()); + + List strings2 = new ArrayList<>(Collections.singletonList("!")); + + strings2.forEach(stringListIterator::add); + } + } + } } class OuterClass { diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java index fe513136456d..71a0cb977274 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/ForCanBeForeachInspectionTest.java @@ -1,7 +1,9 @@ package com.siyeh.ig.migration; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.NotNull; public class ForCanBeForeachInspectionTest extends LightInspectionTestCase { @@ -18,4 +20,10 @@ public class ForCanBeForeachInspectionTest extends LightInspectionTestCase { protected String getBasePath() { return "/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/foreach"; } + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_8; + } } \ No newline at end of file From 30c92a6fd21437c7b55e5050bc855149c209b462 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 12:50:45 +0100 Subject: [PATCH 069/231] mnemonics provided (IDEA-136669) --- .../testIntegration/createTest/CreateTestDialog.java | 8 +++++--- .../src/messages/CodeInsightBundle.properties | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java index a620938830ef..c07294b60351 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java @@ -203,8 +203,8 @@ public class CreateTestDialog extends DialogWrapper { }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK)), myTargetPackageField.getChildComponent()); - myGenerateBeforeBox = new JCheckBox("setUp/@Before"); - myGenerateAfterBox = new JCheckBox("tearDown/@After"); + myGenerateBeforeBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.setUp")); + myGenerateAfterBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.tearDown")); myShowInheritedMethodsBox = new JCheckBox(CodeInsightBundle.message("intention.create.test.dialog.show.inherited")); myShowInheritedMethodsBox.addActionListener(new ActionListener() { @@ -411,7 +411,9 @@ public class CreateTestDialog extends DialogWrapper { constr.gridy = gridy++; constr.gridx = 0; constr.weightx = 0; - panel.add(new JLabel(CodeInsightBundle.message("intention.create.test.dialog.select.methods")), constr); + final JLabel membersLabel = new JLabel(CodeInsightBundle.message("intention.create.test.dialog.select.methods")); + membersLabel.setLabelFor(myMethodsTable); + panel.add(membersLabel, constr); constr.gridx = 1; constr.weightx = 1; diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index 4c4a14eb79b4..1a823a102b9e 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -230,8 +230,10 @@ intention.create.test.dialog.class.name=Class name: intention.create.test.dialog.super.class=Superclass: intention.create.test.dialog.choose.super.class=Choose Superclass intention.create.test.dialog.generate=Generate: -intention.create.test.dialog.show.inherited=Show inherited methods -intention.create.test.dialog.select.methods=Generate test methods for: +intention.create.test.dialog.show.inherited=Show &inherited methods +intention.create.test.dialog.setUp=set&Up/@Before +intention.create.test.dialog.tearDown=tear&Down/@After +intention.create.test.dialog.select.methods=Generate test &methods for: intention.create.test.dialog.library.not.found={0} library not found in the module intention.create.test.dialog.fix.library=Fix intention.create.test.dialog.java=Java From 84750ba9d97be528cc822b00fd9f66a321ba9eb0 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 20 Feb 2015 15:39:44 +0300 Subject: [PATCH 070/231] Notification providing changed, message is shown if: - collection info runnable returns not null string value - not collecting info runnable, which is not reference equal to EmptyRunnable.getInstance(), default value "imports optimized" is shown --- .../actions/OptimizeImportsProcessor.java | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java index 51a92fde83d9..1428605281ff 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java @@ -27,16 +27,19 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.FutureTask; +import static com.intellij.codeInsight.actions.OptimizeImportsProcessor.NotificationInfo.*; + public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { private static final String PROGRESS_TEXT = CodeInsightBundle.message("progress.text.optimizing.imports"); public static final String COMMAND_NAME = CodeInsightBundle.message("process.optimize.imports"); - private List myOptimizersMessages = ContainerUtil.newSmartList(); + private List myOptimizerNotifications = ContainerUtil.newSmartList(); public OptimizeImportsProcessor(Project project) { super(project, COMMAND_NAME, PROGRESS_TEXT, false); @@ -105,10 +108,14 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { private void retrieveAndStoreNotificationInfo(@NotNull Runnable runnable) { if (runnable instanceof ImportOptimizer.CollectingInfoRunnable) { - String info = ((ImportOptimizer.CollectingInfoRunnable)runnable).getUserNotificationInfo(); - if (info != null) { - myOptimizersMessages.add(info); - } + String optimizerMessage = ((ImportOptimizer.CollectingInfoRunnable)runnable).getUserNotificationInfo(); + myOptimizerNotifications.add(optimizerMessage != null ? new NotificationInfo(optimizerMessage) : NOTHING_CHANGED_NOTIFICATION); + } + else if (runnable == EmptyRunnable.getInstance()) { + myOptimizerNotifications.add(NOTHING_CHANGED_NOTIFICATION); + } + else { + myOptimizerNotifications.add(SOMETHING_CHANGED_WITHOUT_MESSAGE_NOTIFICATION); } } @@ -118,10 +125,40 @@ public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor { return; } - String info = "imports optimized"; - if (myOptimizersMessages.size() == 1) { - info = myOptimizersMessages.get(0); + boolean atLeastOneOptimizerChangedSomething = false; + for (NotificationInfo info : myOptimizerNotifications) { + atLeastOneOptimizerChangedSomething |= info.isSomethingChanged(); + if (info.getMessage() != null) { + collector.setOptimizeImportsNotification(info.getMessage()); + return; + } + } + + collector.setOptimizeImportsNotification(atLeastOneOptimizerChangedSomething ? "imports optimized" : null); + } + + static class NotificationInfo { + public static final NotificationInfo NOTHING_CHANGED_NOTIFICATION = new NotificationInfo(false, null); + public static final NotificationInfo SOMETHING_CHANGED_WITHOUT_MESSAGE_NOTIFICATION = new NotificationInfo(true, null); + + private final boolean mySomethingChanged; + private final String myMessage; + + NotificationInfo(@NotNull String message) { + this(true, message); + } + + public boolean isSomethingChanged() { + return mySomethingChanged; + } + + public String getMessage() { + return myMessage; + } + + private NotificationInfo(boolean isSomethingChanged, @Nullable String message) { + mySomethingChanged = isSomethingChanged; + myMessage = message; } - collector.setOptimizeImportsNotification(info); } } From a2f1d6951c910ab08dda388c3da4b8c1d73da7c8 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 20 Feb 2015 16:07:37 +0300 Subject: [PATCH 071/231] toString implementations for easier debug --- .../debugger/engine/evaluation/expression/DisableGC.java | 5 +++++ .../engine/evaluation/expression/LiteralEvaluator.java | 7 ++++++- .../evaluation/expression/LocalVariableEvaluator.java | 7 ++++++- .../engine/evaluation/expression/MethodEvaluator.java | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java index e4905af7fec5..196995a25013 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/DisableGC.java @@ -46,4 +46,9 @@ public class DisableGC implements Evaluator{ public Modifier getModifier() { return myDelegate.getModifier(); } + + @Override + public String toString() { + return "NoGC -> " + myDelegate; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java index 2f4b85d22609..4597167d9c99 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LiteralEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -66,4 +66,9 @@ class LiteralEvaluator implements Evaluator { throw EvaluateExceptionUtil .createEvaluateException(DebuggerBundle.message("evaluation.error.unknown.expression.type", myExpectedType)); } + + @Override + public String toString() { + return myValue.toString(); + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java index b02ec96fad31..caf0e41c07c3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/LocalVariableEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -156,4 +156,9 @@ class LocalVariableEvaluator implements Evaluator { } return modifier; } + + @Override + public String toString() { + return myLocalVariableName; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java index d495f3d19d08..3aff8225622f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java @@ -211,4 +211,9 @@ public class MethodEvaluator implements Evaluator { } return null; } + + @Override + public String toString() { + return "call " + myMethodName; + } } From 2169bbc921ce0c5664ebf859a22680b609566de5 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 20 Feb 2015 16:09:17 +0300 Subject: [PATCH 072/231] avoid unknown class in quick eval --- .../engine/evaluation/expression/EvaluatorBuilderImpl.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index 2363cf9f93ba..8779d9f94b91 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -952,11 +952,10 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } if (qualifier instanceof PsiReferenceExpression && ((PsiReferenceExpression)qualifier).resolve() instanceof PsiClass) { - // this is a call to a 'static' method - if (contextClass == null && type == null) { - throwEvaluateException(DebuggerBundle.message("evaluation.error.qualifier.type.unknown", qualifier.getText())); + // this is a call to a 'static' method but class is not available, try to evaluate by qname + if (contextClass == null) { + contextClass = JVMNameUtil.getJVMRawText(((PsiReferenceExpression)qualifier).getQualifiedName()); } - assert contextClass != null; objectEvaluator = new TypeEvaluator(contextClass); } else { From 102924971c573f8dfccbc7f05c344989f7f97379 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 19 Feb 2015 19:03:00 +0100 Subject: [PATCH 073/231] SSR: fix replacing for with foreach --- .../structuralsearch/JavaStructuralSearchProfile.java | 3 ++- .../intellij/structuralsearch/StructuralReplaceTest.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index 93e35b20b965..9b7c1c6cdf29 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -446,7 +446,8 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { ParameterInfo nameInfo = builder.findParameterization(name); ParameterInfo typeInfo = builder.findParameterization(type); - if (nameInfo != null && typeInfo != null && !(parameter.getParent() instanceof PsiCatchSection)) { + final PsiElement scope = parameter.getDeclarationScope(); + if (nameInfo != null && typeInfo != null && !(scope instanceof PsiCatchSection) && !(scope instanceof PsiForeachStatement)) { nameInfo.setArgumentContext(false); typeInfo.setArgumentContext(false); typeInfo.setMethodParameterContext(true); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index 54be5b887f9d..250a57e3811c 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -449,7 +449,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { actualResult ); - /*String s55 = "for(Iterator iterator = stringlist.iterator(); iterator.hasNext();) {\n" + + String s55 = "for(Iterator iterator = stringlist.iterator(); iterator.hasNext();) {\n" + " String str = iterator.next();\n" + " System.out.println( str );\n" + "}"; @@ -460,7 +460,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { String s57 = "for($Type$ $var$:$container$) {\n" + " $Statements$;\n" + "}"; - String expectedResult20 = "for(String str :stringlist) {\n" + + String expectedResult20 = "for(String str:stringlist) {\n" + " System.out.println( str );\n" + "}"; @@ -470,7 +470,7 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { "for with foreach", expectedResult20, actualResult - );*/ + ); String s58 = "class A {\n" + " static Set b_MAP = new HashSet();\n" + From 90fcf392cca36a5361656b8645c33ca8cbb9c80d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 20 Feb 2015 11:15:00 +0100 Subject: [PATCH 074/231] EA-65194 (IAE: ContainerUtil.collectSet) --- .../com/intellij/structuralsearch/MatchOptions.java | 6 +++--- .../plugin/ui/EditVarConstraintsDialog.java | 12 ++++++------ .../structuralsearch/plugin/ui/SearchDialog.java | 8 +++----- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java index 4c21d8f6892b..2d67883ad6e3 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java @@ -77,9 +77,9 @@ public class MatchOptions implements JDOMExternalizable { return null; } - public Iterator getVariableConstraintNames() { - if (variableConstraints==null) return null; - return variableConstraints.keySet().iterator(); + public Set getVariableConstraintNames() { + if (variableConstraints==null) return Collections.emptySet(); + return Collections.unmodifiableSet(variableConstraints.keySet()); } public void setCaseSensitiveMatch(boolean caseSensitiveMatch) { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java index 258aaf6b8ccc..49a3aee760f1 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java @@ -48,8 +48,8 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; import java.util.List; -import java.util.Set; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -226,10 +226,10 @@ class EditVarConstraintsDialog extends DialogWrapper { customScriptCode.getButton().addActionListener(new ActionListener() { public void actionPerformed(@NotNull final ActionEvent e) { - Set strings = ContainerUtil.collectSet(model.getConfig().getMatchOptions().getVariableConstraintNames()); - strings.remove(current.getName()); - strings.remove(CompiledPattern.ALL_CLASS_UNMATCHED_CONTENT_VAR_ARTIFICIAL_NAME); - EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText(), strings); + final List variableNames = ContainerUtil.newArrayList(model.getConfig().getMatchOptions().getVariableConstraintNames()); + variableNames.remove(current.getName()); + variableNames.remove(CompiledPattern.ALL_CLASS_UNMATCHED_CONTENT_VAR_ARTIFICIAL_NAME); + final EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText(), variableNames); dialog.show(); if (dialog.getExitCode() == OK_EXIT_CODE) { customScriptCode.getChildComponent().setText(dialog.getScriptText()); @@ -593,7 +593,7 @@ class EditVarConstraintsDialog extends DialogWrapper { private final Editor editor; private final String title; - public EditScriptDialog(Project project, String text, Set names) { + public EditScriptDialog(Project project, String text, Collection names) { super(project, true); setTitle(SSRBundle.message("edit.groovy.script.constraint.title")); editor = createEditor(project, text, "1.groovy"); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java index 0720cac36c20..7fa3d5ee7716 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java @@ -436,11 +436,9 @@ public class SearchDialog extends DialogWrapper { ); model.getConfig().getMatchOptions().clearVariableConstraints(); - if (matchOptions.hasVariableConstraints()) { - for (Iterator i = matchOptions.getVariableConstraintNames(); i.hasNext(); ) { - final MatchVariableConstraint constraint = (MatchVariableConstraint)matchOptions.getVariableConstraint(i.next()).clone(); - model.getConfig().getMatchOptions().addVariableConstraint(constraint); - } + for (String name : matchOptions.getVariableConstraintNames()) { + final MatchVariableConstraint constraint = (MatchVariableConstraint)matchOptions.getVariableConstraint(name).clone(); + model.getConfig().getMatchOptions().addVariableConstraint(constraint); } MatchOptions options = configuration.getMatchOptions(); From 8fff0ae91dd4bdb2281bf653596d59a6ad204ded Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 20 Feb 2015 11:25:46 +0100 Subject: [PATCH 075/231] SSR: use a label instead of a text field --- .../plugin/ui/EditVarConstraintsDialog.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java index 49a3aee760f1..632140192b31 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java @@ -612,13 +612,10 @@ class EditVarConstraintsDialog extends DialogWrapper { } protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new BorderLayout()); + final JPanel panel = new JPanel(new BorderLayout()); panel.add(editor.getComponent(), BorderLayout.CENTER); if (!title.isEmpty()) { - JTextField f=new JTextField(title); - f.setEditable(false); - f.setBorder(null); - panel.add(f, BorderLayout.SOUTH); + panel.add(new JLabel(title), BorderLayout.SOUTH); } return panel; } From 6b650eefd15042a5634cd481d20543d8a9407556 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 20 Feb 2015 13:02:03 +0100 Subject: [PATCH 076/231] SSR: drop non-functional text constraints from Complete Match variable --- .../plugin/ui/EditVarConstraintsDialog.java | 9 +- .../plugin/ui/VarConstraints.form | 110 ++++++++---------- 2 files changed, 50 insertions(+), 69 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java index 632140192b31..9a137efee3a1 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java @@ -423,13 +423,11 @@ class EditVarConstraintsDialog extends DialogWrapper { invertWithinIn.setSelected(varInfo.isInvertWithinConstraint()); } - boolean isExprContext = true; final boolean contextVar = Configuration.CONTEXT_VAR_NAME.equals(var.getName()); - if (contextVar) isExprContext = false; containedInConstraints.setVisible(contextVar); - expressionConstraints.setVisible(isExprContext); - partOfSearchResults.setEnabled(!contextVar); //? - + textConstraintsPanel.setVisible(!contextVar); + expressionConstraints.setVisible(!contextVar); + partOfSearchResults.setVisible(!contextVar); occurencePanel.setVisible(!contextVar); } @@ -439,7 +437,6 @@ class EditVarConstraintsDialog extends DialogWrapper { expressionConstraints.setVisible(b); partOfSearchResults.setVisible(b); containedInConstraints.setVisible(b); - pack(); } private void restoreScriptCode(NamedScriptableDefinition varInfo) { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form index 20094b213e64..d57ceb3fd293 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/VarConstraints.form @@ -1,6 +1,6 @@
- + @@ -11,7 +11,11 @@ - + + + + + @@ -19,30 +23,20 @@ - - + - + + + - - - - - - - - - - - - + - + @@ -95,7 +89,7 @@ - + @@ -203,7 +197,7 @@ - + @@ -211,52 +205,13 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -315,7 +270,7 @@ - + @@ -341,10 +296,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7c21a75dd70dc14b888b76c8bd72d20129ffc708 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 20 Feb 2015 14:15:50 +0100 Subject: [PATCH 077/231] SSR: __context__ variable should be saved --- .../com/intellij/structuralsearch/plugin/ui/SearchDialog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java index 7fa3d5ee7716..4fe8b7d2201d 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchDialog.java @@ -827,6 +827,7 @@ public class SearchDialog extends DialogWrapper { for (Variable variable : variables) { variableNames.add(variable.getName()); } + variableNames.add(Configuration.CONTEXT_VAR_NAME); configuration.getMatchOptions().retainVariableConstraints(variableNames); } From 652bb27c48c689695fc76538328842d5e78f506c Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Fri, 20 Feb 2015 16:55:43 +0300 Subject: [PATCH 078/231] IDEA-136787 MacOS: Selecting SNAPSHOT as IntelliJ Platform Plugin SDK fails --- build/scripts/utils.gant | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 7421c91f9cc5..22c4afadea82 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -453,6 +453,12 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args -> ant.move(file: "$path/bin/inspect.sh", tofile: "$path/bin/${args.inspect_script}.sh") } + ant.move(todir: "$path/Resources") { + fileset(dir: "$path") { + include(name: "*.txt") + } + } + ant.fixcrlf(srcdir: "$path/bin", includes: "*.sh", eol: "unix") }) From 6a8e3b1eecbcce7a805a842256e238b28048ec15 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 20 Feb 2015 16:55:50 +0300 Subject: [PATCH 079/231] Added action text --- .../platform-resources-en/src/messages/ActionsBundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index df4aa168e8fa..93cb7ce861d0 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -548,6 +548,7 @@ action.OptimizeImports.text=Optimi_ze Imports... action.OptimizeImports.description=Remove unused imports and reorder/reorganize imports action.RearrangeCode.text=Rearrange Code action.RearrangeCode.description=Rearrange code +action.ReformatFile.text=Show Reformat File Dialog action.MoveStatementDown.text=Move Statement Do_wn action.MoveStatementDown.description=Move selected statements one line down action.MoveStatementUp.text=Move Statement _Up From f8ef7cd72260d1a78ffb34b8df252f2937ad53f8 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 20 Feb 2015 16:59:18 +0300 Subject: [PATCH 080/231] Renamed ReformatFile action to ShowReformatFileDialog --- .../com/intellij/codeInsight/actions/FileInEditorProcessor.java | 2 +- .../{ReformatFileAction.java => ShowReformatFileDialog.java} | 2 +- .../platform-resources-en/src/messages/ActionsBundle.properties | 2 +- platform/platform-resources/src/idea/Keymap_Default.xml | 2 +- platform/platform-resources/src/idea/LangActions.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename platform/lang-impl/src/com/intellij/codeInsight/actions/{ReformatFileAction.java => ShowReformatFileDialog.java} (97%) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java index 33813c5a5b45..75f4c1f3c92e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FileInEditorProcessor.java @@ -166,7 +166,7 @@ class FileInEditorProcessor { } } - String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ReformatFile")); + String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ShowReformatFileDialog")); String color = ColorUtil.toHex(JBColor.gray); builder.append("") diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ShowReformatFileDialog.java similarity index 97% rename from platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java rename to platform/lang-impl/src/com/intellij/codeInsight/actions/ShowReformatFileDialog.java index 2855b205e5e3..b564b939ea1e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFileAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ShowReformatFileDialog.java @@ -24,7 +24,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NonNls; -public class ReformatFileAction extends AnAction implements DumbAware { +public class ShowReformatFileDialog extends AnAction implements DumbAware { private static final @NonNls String HELP_ID = "editing.codeReformatting"; @Override diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 93cb7ce861d0..727d96663ff5 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -548,7 +548,7 @@ action.OptimizeImports.text=Optimi_ze Imports... action.OptimizeImports.description=Remove unused imports and reorder/reorganize imports action.RearrangeCode.text=Rearrange Code action.RearrangeCode.description=Rearrange code -action.ReformatFile.text=Show Reformat File Dialog +action.ShowReformatFileDialog.text=Show Reformat File Dialog action.MoveStatementDown.text=Move Statement Do_wn action.MoveStatementDown.description=Move selected statements one line down action.MoveStatementUp.text=Move Statement _Up diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index c6cbf44e4aa0..5ce4479f0491 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -87,7 +87,7 @@ - + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index db5c66ede0cc..cc37df8bfb68 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -938,7 +938,7 @@ - + From 7cf55c1aef4c1791380c2ee24511af83b9806e16 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 20 Feb 2015 17:16:07 +0300 Subject: [PATCH 081/231] cleanup --- .../debugger/actions/ShowLibraryFramesAction.java | 7 ++++--- .../debugger/engine/JavaDebugProcess.java | 15 +++++---------- .../intellij/debugger/ui/DebuggerSessionTab.java | 9 ++++----- .../src/com/intellij/debugger/ui/FramesPanel.java | 6 +++--- resources/src/idea/JavaActions.xml | 1 - 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java index 972cfef48661..6c53669dd810 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ShowLibraryFramesAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.xdebugger.impl.XDebuggerUtilImpl; +import org.jetbrains.annotations.NotNull; /** * @author egor @@ -36,10 +37,10 @@ public class ShowLibraryFramesAction extends ToggleAction { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean shouldShow = !(Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean shouldShow = !Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(shouldShow ? ourTextWhenShowIsOn : ourTextWhenShowIsOff); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java index 0b1cd18bb05b..5dd4279b3cd1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java @@ -137,11 +137,7 @@ public class JavaDebugProcess extends XDebugProcess { myNodeManager = new NodeManagerImpl(session.getProject(), null) { @Override public DebuggerTreeNodeImpl createNode(final NodeDescriptor descriptor, EvaluationContext evaluationContext) { - // value gathered here is required for correct renderers work. e.g. array renderer - //((NodeDescriptorImpl)descriptor).setContext((EvaluationContextImpl)evaluationContext); - final DebuggerTreeNodeImpl node = new DebuggerTreeNodeImpl(null, descriptor); - //((NodeDescriptorImpl)descriptor).updateRepresentation((EvaluationContextImpl)evaluationContext, DescriptorLabelListener.DUMMY_LISTENER); - return node; + return new DebuggerTreeNodeImpl(null, descriptor); } @Override @@ -322,7 +318,6 @@ public class JavaDebugProcess extends XDebugProcess { public void registerAdditionalActions(@NotNull DefaultActionGroup leftToolbar, @NotNull DefaultActionGroup topToolbar, @NotNull DefaultActionGroup settings) { Constraints beforeRunner = new Constraints(Anchor.BEFORE, "Runner.Layout"); leftToolbar.add(Separator.getInstance(), beforeRunner); - //leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.EXPORT_THREADS), beforeRunner); leftToolbar.add(ActionManager.getInstance().getAction(DebuggerActions.DUMP_THREADS), beforeRunner); leftToolbar.add(Separator.getInstance(), beforeRunner); @@ -339,10 +334,10 @@ public class JavaDebugProcess extends XDebugProcess { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean autoModeEnabled = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean autoModeEnabled = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(autoModeEnabled ? "All-Variables Mode" : "Auto-Variables Mode"); } @@ -374,10 +369,10 @@ public class JavaDebugProcess extends XDebugProcess { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean watchValues = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean watchValues = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); DebugProcessImpl process = getCurrentDebugProcess(e.getProject()); final String actionText = watchValues ? myMyTextDisable : myTextEnable; if (process == null || process.canGetMethodReturnValue()) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java index a088e953557f..51a96197ba48 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java @@ -287,7 +287,6 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } leftToolbar.addSeparator(); - //addAction(leftToolbar, DebuggerActions.EXPORT_THREADS); addAction(leftToolbar, DebuggerActions.DUMP_THREADS); leftToolbar.addSeparator(); @@ -523,10 +522,10 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean autoModeEnabled = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean autoModeEnabled = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(autoModeEnabled ? "All-Variables Mode" : "Auto-Variables Mode"); } @@ -558,10 +557,10 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean watchValues = (Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean watchValues = Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); final DebugProcessImpl process = getDebugProcess(); final String actionText = watchValues ? myMyTextDisable : myTextEnable; if (process != null && process.canGetMethodReturnValue()) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java index e17b8af10827..dba4453ae43c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/FramesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -710,10 +710,10 @@ public class FramesPanel extends UpdatableDebuggerView implements DataProvider { } @Override - public void update(final AnActionEvent e) { + public void update(@NotNull final AnActionEvent e) { super.update(e); final Presentation presentation = e.getPresentation(); - final boolean shouldShow = !(Boolean)presentation.getClientProperty(SELECTED_PROPERTY); + final boolean shouldShow = !Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)); presentation.setText(shouldShow ? ourTextWhenShowIsOn : ourTextWhenShowIsOff); } diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 9efac63d0dce..003f61467fa0 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -127,7 +127,6 @@ - From 4ad508a75fdd8804ce0618c21f55ab3b6786eaff Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 20 Feb 2015 17:27:10 +0300 Subject: [PATCH 082/231] removed unused actions --- .../CompareValueWithClipboardAction.java | 34 ---------- .../debugger/actions/CopyValueAction.java | 32 --------- .../debugger/actions/EditWatchAction.java | 51 -------------- .../debugger/actions/NewWatchAction.java | 43 ------------ .../actions/RemoveAllWatchesAction.java | 46 ------------- .../debugger/actions/RemoveWatchAction.java | 68 ------------------- .../ShowExecutionPointActionHandler.java | 38 ----------- resources/src/idea/JavaActions.xml | 6 -- 8 files changed, 318 deletions(-) delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java delete mode 100644 java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java deleted file mode 100644 index 1d6ed15abb59..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.impl.DebuggerContextImpl; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.diff.DiffDialogHints; -import com.intellij.diff.DiffManager; -import com.intellij.diff.DiffRequestFactory; -import com.intellij.diff.requests.DiffRequest; -import com.intellij.openapi.project.Project; - -/** - * @author Jeka - */ -public class CompareValueWithClipboardAction extends BaseValueAction { - protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) { - DiffRequest request = DiffRequestFactory.getInstance().createClipboardVsValue(text); - DiffManager.getInstance().showDiff(project, request); - } -} \ No newline at end of file diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java deleted file mode 100644 index 256566557ae1..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CopyValueAction.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2009 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.debugger.actions; - -import com.intellij.debugger.impl.DebuggerContextImpl; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.openapi.ide.CopyPasteManager; -import com.intellij.openapi.project.Project; - -import java.awt.datatransfer.StringSelection; - -/* - * @author Jeka - */ -public class CopyValueAction extends BaseValueAction { - protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) { - CopyPasteManager.getInstance().setContents(new StringSelection(text)); - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java deleted file mode 100644 index 48bf5acd10bb..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/EditWatchAction.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2009 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.debugger.actions; - -import com.intellij.debugger.ui.DebuggerPanelsManager; -import com.intellij.debugger.ui.impl.MainWatchPanel; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.project.Project; - -/** - * User: lex - * Date: Sep 26, 2003 - * Time: 8:34:01 PM - */ -public class EditWatchAction extends DebuggerAction { - public void actionPerformed(final AnActionEvent e) { - final DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - if(selectedNode == null || !(selectedNode.getDescriptor() instanceof WatchItemDescriptor)) return; - - Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - - MainWatchPanel watchPanel = DebuggerPanelsManager.getInstance(project).getWatchPanel(); - if(watchPanel != null) { - watchPanel.editNode(selectedNode); - } - } - - public void update(AnActionEvent e) { - final DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - - e.getPresentation().setVisible(selectedNode != null && selectedNode.getDescriptor() instanceof WatchItemDescriptor); - } - -}; diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java deleted file mode 100644 index 6a8d3fe017df..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/NewWatchAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -/* - * Class NewWatchAction - * @author Jeka - */ -package com.intellij.debugger.actions; - -import com.intellij.debugger.ui.DebuggerPanelsManager; -import com.intellij.debugger.ui.impl.MainWatchPanel; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -public class NewWatchAction extends DebuggerAction { - public void actionPerformed(final AnActionEvent e) { - getWatchPanel(e).newWatch(); - } - - @Override - public void update(@NotNull AnActionEvent e) { - e.getPresentation().setEnabled(getWatchPanel(e) != null); - } - - private static MainWatchPanel getWatchPanel(AnActionEvent e) { - Project project = e.getProject(); - return project != null ? DebuggerPanelsManager.getInstance(project).getWatchPanel() : null; - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java deleted file mode 100644 index e6773227cc1c..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveAllWatchesAction.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2000-2009 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.debugger.actions; - -import com.intellij.debugger.ui.impl.watch.DebuggerTree; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.Presentation; - -import java.util.Enumeration; - -/** - * User: lex - * Date: Sep 26, 2003 - * Time: 6:24:44 PM - */ -public class RemoveAllWatchesAction extends RemoveWatchAction { - protected DebuggerTreeNodeImpl[] getNodesToDelete(AnActionEvent e) { - DebuggerTree tree = getTree(e.getDataContext()); - if(tree == null) return null; - DebuggerTreeNodeImpl root = (DebuggerTreeNodeImpl)tree.getModel().getRoot(); - DebuggerTreeNodeImpl [] result = new DebuggerTreeNodeImpl[root.getChildCount()]; - int i = 0; - for(Enumeration enumeration = root.children(); enumeration.hasMoreElements(); i++) { - DebuggerTreeNodeImpl node = (DebuggerTreeNodeImpl)enumeration.nextElement(); - result[i] = node; - } - return result; - } - - protected void updatePresentation(Presentation presentation, int watchesCount) { - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java deleted file mode 100644 index 322241943357..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/RemoveWatchAction.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2000-2009 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.debugger.actions; - -import com.intellij.debugger.ui.impl.MainWatchPanel; -import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor; -import com.intellij.debugger.DebuggerBundle; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.Presentation; - -import java.util.ArrayList; - -public class RemoveWatchAction extends DebuggerAction { - protected DebuggerTreeNodeImpl[] getNodesToDelete(AnActionEvent e) { - DebuggerTreeNodeImpl[] selectedNodes = getSelectedNodes(e.getDataContext()); - if(selectedNodes == null) return null; - ArrayList selectedWatches = new ArrayList(); - for (int i = 0; i < selectedNodes.length; i++) { - if(selectedNodes[i].getDescriptor() instanceof WatchItemDescriptor) { - selectedWatches.add(selectedNodes[i]); - } - } - - return selectedWatches.toArray(new DebuggerTreeNodeImpl[selectedWatches.size()]); - } - - public void actionPerformed(AnActionEvent e) { - DebuggerTreeNodeImpl [] nodes = getNodesToDelete(e); - if (nodes == null || nodes.length == 0) return; - - MainWatchPanel watchPanel = (MainWatchPanel)getPanel(e.getDataContext()); - - for (int i = 0; i < nodes.length; i++) { - DebuggerTreeNodeImpl node = nodes[i]; - watchPanel.getWatchTree().removeWatch(node); - } - } - - protected void updatePresentation(Presentation presentation, int watchesCount) { - presentation.setText(DebuggerBundle.message("action.remove.watch.text", watchesCount)); - } - - public void update(AnActionEvent event) { - Presentation presentation = event.getPresentation(); - DebuggerTreeNodeImpl[] nodes = getNodesToDelete(event); - if (nodes != null && nodes.length > 0) { - presentation.setEnabled(true); - } - else { - presentation.setEnabled(false); - } - updatePresentation(presentation, nodes != null? nodes.length : 0); - } -} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java deleted file mode 100644 index f80bab05b6ad..000000000000 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ShowExecutionPointActionHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2000-2009 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.debugger.actions; - -import com.intellij.debugger.DebuggerManagerEx; -import com.intellij.debugger.impl.DebuggerSession; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.Project; -import com.intellij.xdebugger.impl.actions.DebuggerActionHandler; -import org.jetbrains.annotations.NotNull; - -public class ShowExecutionPointActionHandler extends DebuggerActionHandler { - public void perform(@NotNull final Project project, final AnActionEvent event) { - final DebuggerSession session = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession(); - if (session != null) { - session.showExecutionPoint(); - } - } - - public boolean isEnabled(@NotNull final Project project, final AnActionEvent event) { - DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession(); - return debuggerSession != null && debuggerSession.isPaused() && - debuggerSession.getContextManager().getContext().getSuspendContext().getThread() != null; - } -} \ No newline at end of file diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 003f61467fa0..149611088058 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -165,19 +165,13 @@ - - - - - - From 28632c15b12ca46cca5f94b6300fecbc2080b23a Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Fri, 20 Feb 2015 17:57:30 +0300 Subject: [PATCH 083/231] IDEA-136787 MacOS: Selecting SNAPSHOT as IntelliJ Platform Plugin SDK fails. --- build/scripts/utils.gant | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 22c4afadea82..12a2a523c743 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -453,12 +453,6 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args -> ant.move(file: "$path/bin/inspect.sh", tofile: "$path/bin/${args.inspect_script}.sh") } - ant.move(todir: "$path/Resources") { - fileset(dir: "$path") { - include(name: "*.txt") - } - } - ant.fixcrlf(srcdir: "$path/bin", includes: "*.sh", eol: "unix") }) @@ -790,6 +784,8 @@ binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, exclude(name: "bin/fsnotifier") exclude(name: "bin/restarter") exclude(name: "MacOS/*") + exclude(name: "build.txt") + exclude(name: "NOTICE.txt") extraBins.each { exclude(name: it) } @@ -810,6 +806,13 @@ binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, } } + allPaths.each { + zipfileset(dir: it, prefix: "$zipRoot/Resources") { + include(name: "build.txt") + include(name: "NOTICE.txt") + } + } + zipfileset(file: "$macPath/bin/idea.properties", prefix: "$zipRoot/bin") } }) From fa361fdc54bd2912648e5ee0afb6b68c8c9d651a Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 20 Feb 2015 19:01:50 +0300 Subject: [PATCH 084/231] source searcher: use groupId for maven sources search; related issue: IDEA-135073 IDEA can't download source but it exists in a remote repository --- .../InternetAttachSourceProvider.java | 4 +- .../jarFinder/MavenCentralSourceSearcher.java | 11 +++- .../jarFinder/SonatypeSourceSearcher.java | 13 ++++- .../intellij/jarFinder/SourceSearcher.java | 56 ++++++++++++++++++- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java index c6bb1f199b0e..be42dd7fbf8b 100644 --- a/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java +++ b/java/idea-ui/src/com/intellij/jarFinder/InternetAttachSourceProvider.java @@ -67,7 +67,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { @NotNull @Override public Collection getActions(List orderEntries, final PsiFile psiFile) { - VirtualFile jar = getJarByPsiFile(psiFile); + final VirtualFile jar = getJarByPsiFile(psiFile); if (jar == null) return Collections.emptyList(); final String jarName = jar.getNameWithoutExtension(); @@ -145,7 +145,7 @@ public class InternetAttachSourceProvider implements AttachSourcesProvider { SourceSearcher[] searchers = {new MavenCentralSourceSearcher(), new SonatypeSourceSearcher()}; for (SourceSearcher searcher : searchers) { try { - artifactUrl = searcher.findSourceJar(indicator, artifactId, version); + artifactUrl = searcher.findSourceJar(indicator, artifactId, version, jar); } catch (SourceSearchException e) { LOG.warn(e); diff --git a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java index aeb6c7574a01..7e4ed5639904 100644 --- a/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/MavenCentralSourceSearcher.java @@ -2,6 +2,7 @@ package com.intellij.jarFinder; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; @@ -21,13 +22,19 @@ public class MavenCentralSourceSearcher extends SourceSearcher { @Override protected String findSourceJar(@NotNull ProgressIndicator indicator, @NotNull String artifactId, - @NotNull String version) throws SourceSearchException { + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { try { indicator.setText("Connecting to https://search.maven.org"); indicator.checkCanceled(); - String url = "https://search.maven.org/solrsearch/select?rows=3&wt=xml&q=a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22"; + String url = "https://search.maven.org/solrsearch/select?rows=3&wt=xml&q="; + final String groupId = findMavenGroupId(classesJar, artifactId); + if (groupId != null) { + url += "g:%22" + groupId + "%22%20AND%20"; + } + url += "a:%22" + artifactId + "%22%20AND%20v:%22" + version + "%22%20AND%20l:%22sources%22"; @SuppressWarnings("unchecked") List artifactList = (List)XPath.newInstance("/response/result/doc/str[@name='g']").selectNodes(readDocumentCancelable(indicator, url)); if (artifactList.isEmpty()) { diff --git a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java index b4251970fc10..76d713055a4a 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SonatypeSourceSearcher.java @@ -2,6 +2,7 @@ package com.intellij.jarFinder; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.xpath.XPath; @@ -19,7 +20,10 @@ public class SonatypeSourceSearcher extends SourceSearcher { @Nullable @Override - public String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) + public String findSourceJar(@NotNull final ProgressIndicator indicator, + @NotNull String artifactId, + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { try { indicator.setIndeterminate(true); @@ -28,6 +32,11 @@ public class SonatypeSourceSearcher extends SourceSearcher { indicator.checkCanceled(); String url = "https://oss.sonatype.org/service/local/lucene/search?collapseresults=true&c=sources&a=" + artifactId + "&v=" + version; + String groupId = findMavenGroupId(classesJar, artifactId); + if(groupId != null) { + url += ("&g=" + groupId); + } + List artifactList = (List)XPath.newInstance("/searchNGResponse/data/artifact").selectNodes(readDocumentCancelable(indicator, url)); if (artifactList.isEmpty()) { return null; @@ -50,7 +59,7 @@ public class SonatypeSourceSearcher extends SourceSearcher { return null; } - String groupId = element.getChildTextTrim("groupId"); + groupId = element.getChildTextTrim("groupId"); String repositoryId = artifactHintList.get(0).getChildTextTrim("repositoryId"); return "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=" + diff --git a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java index 3c5d138e2b13..0b97e631148b 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java @@ -2,6 +2,10 @@ package com.intellij.jarFinder; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.StreamUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.HttpRequests; import org.jdom.Document; import org.jdom.JDOMException; @@ -9,19 +13,43 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; /** * @author Sergey Evdokimov */ public abstract class SourceSearcher { + + private static final String MAVEN_POM_ENTRY_PREFIX = "META-INF/maven/"; + /** * @param indicator * @param artifactId * @param version - * @return groupId of found artifact and url. + * @return url of found artifact */ @Nullable - protected abstract String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) throws SourceSearchException; + protected String findSourceJar(@NotNull final ProgressIndicator indicator, @NotNull String artifactId, @NotNull String version) + throws SourceSearchException { + return null; + } + + /** + * @param indicator + * @param artifactId + * @param version + * @param classesJar classes jar + * @return url of found artifact + */ + @Nullable + protected String findSourceJar(@NotNull final ProgressIndicator indicator, + @NotNull String artifactId, + @NotNull String version, + @NotNull VirtualFile classesJar) throws SourceSearchException { + return findSourceJar(indicator, artifactId, version); + } @NotNull protected static Document readDocumentCancelable(final ProgressIndicator indicator, String url) throws IOException { @@ -39,6 +67,30 @@ public abstract class SourceSearcher { } }); } + + @Nullable + protected static String findMavenGroupId(@NotNull VirtualFile classesJar, String artifactId) { + try { + JarFile jarFile = new JarFile(VfsUtilCore.virtualToIoFile(classesJar)); + try { + final Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + final String name = entry.getName(); + if (StringUtil.startsWith(name, MAVEN_POM_ENTRY_PREFIX) && StringUtil.endsWith(name, "/" + artifactId + "/pom.xml")) { + final int index = name.indexOf('/', MAVEN_POM_ENTRY_PREFIX.length()); + return index != -1 ? name.substring(MAVEN_POM_ENTRY_PREFIX.length(), index) : null; + } + } + } + finally { + StreamUtil.closeStream(jarFile); + } + } + catch (IOException ignore) { + } + return null; + } } class SourceSearchException extends Exception { From b9f932266659d4667aa0dd413dd85142fb3ba328 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 20 Feb 2015 12:50:02 +0100 Subject: [PATCH 085/231] =?UTF-8?q?cleanup=20=E2=80=94=20client=20don't=20?= =?UTF-8?q?have=20to=20implement=20yet=20another=20interface=20(SchemeExte?= =?UTF-8?q?nsionProvider)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../openapi/options/BaseSchemeProcessor.java | 13 ++- .../options/SchemeExtensionProvider.java | 0 .../openapi/options/SharedScheme.java | 45 -------- .../colors/impl/EditorColorsManagerImpl.java | 104 ++++++++---------- .../openapi/options/SchemesManagerImpl.java | 22 ++-- 5 files changed, 68 insertions(+), 116 deletions(-) rename platform/{platform-api => core-api}/src/com/intellij/openapi/options/SchemeExtensionProvider.java (100%) delete mode 100644 platform/core-api/src/com/intellij/openapi/options/SharedScheme.java diff --git a/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java b/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java index 845e50fbe804..e9630d633000 100644 --- a/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java +++ b/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java @@ -27,7 +27,7 @@ import java.io.IOException; /** * @author yole */ -public abstract class BaseSchemeProcessor implements SchemeProcessor { +public abstract class BaseSchemeProcessor implements SchemeProcessor, SchemeExtensionProvider { @Override public void initScheme(@NotNull T scheme) { } @@ -75,4 +75,15 @@ public abstract class BaseSchemeProcessor implem public State getState(@NotNull T scheme) { return shouldBeSaved(scheme) ? State.POSSIBLY_CHANGED : State.NON_PERSISTENT; } + + @Override + public boolean isUpgradeNeeded() { + return false; + } + + @NotNull + @Override + public String getSchemeExtension() { + return ".xml"; + } } diff --git a/platform/platform-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java b/platform/core-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java similarity index 100% rename from platform/platform-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java rename to platform/core-api/src/com/intellij/openapi/options/SchemeExtensionProvider.java diff --git a/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java b/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java deleted file mode 100644 index a0f59d39f521..000000000000 --- a/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java +++ /dev/null @@ -1,45 +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.openapi.options; - -import org.jetbrains.annotations.NotNull; - -@Deprecated -public class SharedScheme { - private final String myUserName; - private final String myDescription; - private final E myScheme; - - public SharedScheme(@NotNull String userName, final String description, @NotNull E scheme) { - myUserName = userName; - myDescription = description; - myScheme = scheme; - } - - @NotNull - public String getUserName() { - return myUserName; - } - - public String getDescription() { - return myDescription; - } - - @NotNull - public E getScheme() { - return myScheme; - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java index a433a1d6f445..1421aef3e99c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java @@ -56,7 +56,7 @@ import java.util.Comparator; import java.util.List; public class EditorColorsManagerImpl extends EditorColorsManager implements NamedJDOMExternalizable, ExportableComponent, NamedComponent { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl"); + private static final Logger LOG = Logger.getInstance(EditorColorsManagerImpl.class); private final EventDispatcher myListeners = EventDispatcher.create(EditorColorsListener.class); @@ -76,9 +76,49 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name public EditorColorsManagerImpl(DefaultColorSchemesManager defaultColorSchemesManager, SchemesManagerFactory schemesManagerFactory) { myDefaultColorSchemesManager = defaultColorSchemesManager; - mySchemesManager = schemesManagerFactory.createSchemesManager( - FILE_SPEC, - new MySchemeProcessor(), RoamingType.PER_USER); + mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, new BaseSchemeProcessor() { + @NotNull + @Override + public EditorColorsSchemeImpl readScheme(@NotNull Element element) throws InvalidDataException { + return loadSchemeFromDocument(element, true); + } + + @Override + public Element writeScheme(@NotNull final EditorColorsSchemeImpl scheme) { + Element root = new Element(SCHEME_NODE_NAME); + try { + scheme.writeExternal(root); + } + catch (WriteExternalException e) { + LOG.error(e); + return null; + } + + return root; + } + + @NotNull + @Override + public State getState(@NotNull EditorColorsSchemeImpl scheme) { + return scheme instanceof ReadOnlyColorsScheme ? State.NON_PERSISTENT : State.POSSIBLY_CHANGED; + } + + @Override + public void onCurrentSchemeChanged(final Scheme newCurrentScheme) { + fireChanges(mySchemesManager.getCurrentScheme()); + } + + @NotNull + @Override + public String getSchemeExtension() { + return FILE_EXT; + } + + @Override + public boolean isUpgradeNeeded() { + return true; + } + }, RoamingType.PER_USER); addDefaultSchemes(); @@ -184,10 +224,6 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name return scheme; } - // ------------------------------------------------------------------------- - // Schemes manipulation routines - // ------------------------------------------------------------------------- - @Override public void addColorsScheme(@NotNull EditorColorsScheme scheme) { if (!isDefaultScheme(scheme) && scheme.getName().trim().length() > 0) { @@ -208,10 +244,6 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } } - // ------------------------------------------------------------------------- - // Getters & Setters - // ------------------------------------------------------------------------- - @NotNull @Override public EditorColorsScheme[] getAllSchemes() { @@ -268,10 +300,6 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name myListeners.getMulticaster().globalSchemeChange(scheme); } - // ------------------------------------------------------------------------- - // Routines responsible for loading & saving colors schemes. - // ------------------------------------------------------------------------- - private static File getColorsDir(boolean create) { @NonNls String directoryPath = PathManager.getConfigPath() + File.separator + "colors"; File directory = new File(directoryPath); @@ -368,48 +396,4 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name public String getComponentName() { return "EditorColorsManagerImpl"; } - - private final class MySchemeProcessor extends BaseSchemeProcessor implements SchemeExtensionProvider { - @NotNull - @Override - public EditorColorsSchemeImpl readScheme(@NotNull Element element) throws InvalidDataException { - return loadSchemeFromDocument(element, true); - } - - @Override - public Element writeScheme(@NotNull final EditorColorsSchemeImpl scheme) { - Element root = new Element(SCHEME_NODE_NAME); - try { - scheme.writeExternal(root); - } - catch (WriteExternalException e) { - LOG.error(e); - return null; - } - - return root; - } - - @NotNull - @Override - public State getState(@NotNull EditorColorsSchemeImpl scheme) { - return scheme instanceof ReadOnlyColorsScheme ? State.NON_PERSISTENT : State.POSSIBLY_CHANGED; - } - - @Override - public void onCurrentSchemeChanged(final Scheme newCurrentScheme) { - fireChanges(mySchemesManager.getCurrentScheme()); - } - - @NotNull - @Override - public String getSchemeExtension() { - return FILE_EXT; - } - - @Override - public boolean isUpgradeNeeded() { - return true; - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java index a8243ab67d1b..58bf8e6ecb64 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java @@ -69,7 +69,7 @@ public class SchemesManagerImpl myFilesToDelete = new THashSet(); @@ -85,7 +85,7 @@ public class SchemesManagerImpl Date: Fri, 20 Feb 2015 13:27:11 +0100 Subject: [PATCH 086/231] don't load default state from resources by default --- .../debugger/settings/DebuggerSettings.java | 6 ++---- .../colors/ex/DefaultColorSchemesManager.java | 4 ++-- .../execution/impl/RunManagerImpl.java | 1 + .../impl/stores/ComponentStoreImpl.java | 3 +-- .../openapi/wm/impl/WindowManagerImpl.java | 3 ++- .../src/META-INF/PlatformExtensions.xml | 1 - .../intellij/openapi/components/State.java | 5 +++++ resources/src/idea/ContextViewSettings.xml | 3 --- resources/src/idea/Debugger.xml | 19 ------------------- resources/src/idea/UsageViewSettings.xml | 3 --- 10 files changed, 13 insertions(+), 35 deletions(-) delete mode 100644 resources/src/idea/ContextViewSettings.xml delete mode 100644 resources/src/idea/Debugger.xml delete mode 100644 resources/src/idea/UsageViewSettings.xml diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java index 2855ab4dfc1f..7d654d621549 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSettings.java @@ -35,10 +35,8 @@ import java.util.Map; @State( name = "DebuggerSettings", - storages = { - @Storage( - file = StoragePathMacros.APP_CONFIG + "/other.xml" - )} + defaultStateAsResource = true, + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") ) public class DebuggerSettings implements Cloneable, PersistentStateComponent { private static final Logger LOG = Logger.getInstance(DebuggerSettings.class); diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java index 53ac33ba72fc..bd90843372ea 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -28,6 +28,7 @@ import java.util.List; @State( name = "DefaultColorSchemesManager", + defaultStateAsResource = true, storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") ) public class DefaultColorSchemesManager implements PersistentStateComponent { @@ -71,7 +72,6 @@ public class DefaultColorSchemesManager implements PersistentStateComponent, NamedComponent, Disposable { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 16c1567ed63d..5e78e340a581 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -281,8 +281,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } Class stateClass = ComponentSerializationUtil.getStateClass(component.getClass()); - T state = getDefaultState(component, name, stateClass); - + T state = stateSpec.defaultStateAsResource() ? getDefaultState(component, name, stateClass) : null; Storage[] storageSpecs = getComponentStorageSpecs(component, stateSpec, StateStorageOperation.READ); for (Storage storageSpec : storageSpecs) { StateStorage stateStorage = getStateStorageManager().getStateStorage(storageSpec); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java index 4bb301ba7918..4062cd2f317d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java @@ -62,7 +62,8 @@ import java.util.Set; */ @State( name = "WindowManager", - storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml", roamingType = RoamingType.DISABLED)} + defaultStateAsResource = true, + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml", roamingType = RoamingType.DISABLED) ) public final class WindowManagerImpl extends WindowManagerEx implements NamedComponent, PersistentStateComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowManagerImpl"); diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index d156e5efda6a..66c338b02eb1 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -167,7 +167,6 @@ serviceImplementation="com.intellij.openapi.editor.colors.impl.TextAttributeKeyDefaultsProviderImpl"/> - diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/State.java b/platform/projectModel-api/src/com/intellij/openapi/components/State.java index 35cddbd5d16a..6db1cec2205d 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/State.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/State.java @@ -36,6 +36,11 @@ public @interface State { boolean reloadable() default true; + /** + * If true, default state will be loaded from resources (if exists) + */ + boolean defaultStateAsResource() default false; + String additionalExportFile() default ""; Class presentableName() default NameGetter.class; diff --git a/resources/src/idea/ContextViewSettings.xml b/resources/src/idea/ContextViewSettings.xml deleted file mode 100644 index 8f467b7bcd7d..000000000000 --- a/resources/src/idea/ContextViewSettings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - diff --git a/resources/src/idea/Debugger.xml b/resources/src/idea/Debugger.xml deleted file mode 100644 index 18ba69f6ebd7..000000000000 --- a/resources/src/idea/Debugger.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/resources/src/idea/UsageViewSettings.xml b/resources/src/idea/UsageViewSettings.xml deleted file mode 100644 index cc4fea038944..000000000000 --- a/resources/src/idea/UsageViewSettings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - From 9965d8e51e2407e025f9c8e4cc8b2d2b06009975 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 20 Feb 2015 17:06:44 +0100 Subject: [PATCH 087/231] IDEA-136776 As of 14.1 IDEA Color & Font theme resets after every restart to default --- .../openapi/editor/markup/TextAttributes.java | 24 +- .../openapi/options/SchemesManager.java | 87 ++----- .../options/AbstractSchemesManager.java | 2 +- .../openapi/options/EmptySchemesManager.java | 78 ++++++ .../editor/colors/EditorColorsScheme.java | 6 +- .../colors/ex/DefaultColorSchemesManager.java | 10 +- .../colors/impl/AbstractColorsScheme.java | 136 +++++----- .../colors/impl/DefaultColorsScheme.java | 11 +- .../colors/impl/EditorColorsSchemeImpl.java | 8 +- .../usageView/UsageTreeColorsScheme.java | 6 +- .../options/colors/ColorAndFontOptions.java | 4 +- .../actionSystem/ex/QuickListsManager.java | 23 +- .../colors/impl/DelegateColorScheme.java | 9 +- .../colors/impl/EditorColorsManagerImpl.java | 243 ++++++------------ .../colors/impl/ReadOnlyColorsSchemeImpl.java | 29 --- .../openapi/options/SchemesManagerImpl.java | 22 ++ .../src/messages/OptionsBundle.properties | 4 +- .../impl/EditorColorsSchemeImplTest.java | 15 +- .../MockSchemesManagerFactory.java | 5 +- .../JBTerminalSystemSettingsProvider.java | 8 +- 20 files changed, 318 insertions(+), 412 deletions(-) create mode 100644 platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java delete mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java diff --git a/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java b/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java index c9d4bd59ec59..bd98d77dd987 100644 --- a/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java +++ b/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java @@ -17,8 +17,6 @@ package com.intellij.openapi.editor.markup; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMExternalizable; -import com.intellij.openapi.util.WriteExternalException; import org.intellij.lang.annotations.JdkConstants; import org.jdom.Element; import org.jetbrains.annotations.Contract; @@ -30,7 +28,7 @@ import java.awt.*; /** * Defines the visual representation (colors and effects) of text. */ -public class TextAttributes implements JDOMExternalizable, Cloneable { +public class TextAttributes implements Cloneable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.markup.TextAttributes"); public static final TextAttributes ERASE_MARKER = new TextAttributes(); @@ -77,7 +75,7 @@ public class TextAttributes implements JDOMExternalizable, Cloneable { myEnforcedDefaults = enforced; } - public TextAttributes(@NotNull Element element) throws InvalidDataException { + public TextAttributes(@NotNull Element element) { readExternal(element); } @@ -191,14 +189,20 @@ public class TextAttributes implements JDOMExternalizable, Cloneable { return myAttrs.hashCode(); } - @Override - public void readExternal(Element element) throws InvalidDataException { - myAttrs = AttributesFlyweight.create(element); - if (isEmpty()) myEnforcedDefaults = true; + public void readExternal(Element element) { + try { + myAttrs = AttributesFlyweight.create(element); + } + catch (InvalidDataException e) { + throw new RuntimeException(e); + } + + if (isEmpty()) { + myEnforcedDefaults = true; + } } - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void writeExternal(Element element) { myAttrs.writeExternal(element); } diff --git a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java index cef94aefcc06..c085400d9465 100644 --- a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java +++ b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java @@ -15,94 +15,43 @@ */ package com.intellij.openapi.options; +import com.intellij.util.ThrowableConvertor; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.Collection; -import java.util.Collections; import java.util.List; -public interface SchemesManager { - SchemesManager EMPTY = new SchemesManager(){ - @Override - @NotNull - public Collection loadSchemes() { - return Collections.emptySet(); - } +public abstract class SchemesManager { + @NotNull + public abstract Collection loadSchemes(); - @Override - public void addNewScheme(@NotNull final Scheme scheme, final boolean replaceExisting) { - } + public abstract void addNewScheme(@NotNull T scheme, final boolean replaceExisting); - @Override - public void clearAllSchemes() { - } - - @Override - @NotNull - public List getAllSchemes() { - return Collections.emptyList(); - } - - @Override - public Scheme findSchemeByName(@NotNull String schemeName) { - return null; - } - - @Override - public void save() { - } - - @Override - public void setCurrentSchemeName(String schemeName) { - } - - @Override - public Scheme getCurrentScheme() { - return null; - } - - @Override - public void removeScheme(@NotNull Scheme scheme) { - } - - @Override - @NotNull - public Collection getAllSchemeNames() { - return Collections.emptySet(); - } - - @Override - public File getRootDirectory() { - return null; - } - }; + public abstract void clearAllSchemes(); @NotNull - Collection loadSchemes(); - - void addNewScheme(@NotNull T scheme, final boolean replaceExisting); - - void clearAllSchemes(); - - @NotNull - List getAllSchemes(); + public abstract List getAllSchemes(); @Nullable - T findSchemeByName(@NotNull String schemeName); + public abstract T findSchemeByName(@NotNull String schemeName); - void save(); + public abstract void save(); - void setCurrentSchemeName(@Nullable String schemeName); + public abstract void setCurrentSchemeName(@Nullable String schemeName); @Nullable - T getCurrentScheme(); + public abstract T getCurrentScheme(); - void removeScheme(@NotNull T scheme); + public abstract void removeScheme(@NotNull T scheme); @NotNull - Collection getAllSchemeNames(); + public abstract Collection getAllSchemeNames(); - File getRootDirectory(); + public abstract File getRootDirectory(); + + public void loadBundledScheme(@NotNull String resourceName, @NotNull Object requestor, @NotNull ThrowableConvertor convertor) { + } } diff --git a/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java b/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java index d4f3f707d4e6..14f3b057a5fc 100644 --- a/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java +++ b/platform/core-impl/src/com/intellij/openapi/options/AbstractSchemesManager.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -public abstract class AbstractSchemesManager implements SchemesManager { +public abstract class AbstractSchemesManager extends SchemesManager { private static final Logger LOG = Logger.getInstance(AbstractSchemesManager.class); protected final List mySchemes = new ArrayList(); diff --git a/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java b/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java new file mode 100644 index 000000000000..55a74d08ebd1 --- /dev/null +++ b/platform/core-impl/src/com/intellij/openapi/options/EmptySchemesManager.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.options; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class EmptySchemesManager extends SchemesManager { + @Override + @NotNull + public Collection loadSchemes() { + return Collections.emptySet(); + } + + @Override + public void addNewScheme(@NotNull final Scheme scheme, final boolean replaceExisting) { + } + + @Override + public void clearAllSchemes() { + } + + @Override + @NotNull + public List getAllSchemes() { + return Collections.emptyList(); + } + + @Override + public Scheme findSchemeByName(@NotNull String schemeName) { + return null; + } + + @Override + public void save() { + } + + @Override + public void setCurrentSchemeName(String schemeName) { + } + + @Override + public Scheme getCurrentScheme() { + return null; + } + + @Override + public void removeScheme(@NotNull Scheme scheme) { + } + + @Override + @NotNull + public Collection getAllSchemeNames() { + return Collections.emptySet(); + } + + @Override + public File getRootDirectory() { + return null; + } +} diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java index d19658d588fb..085fecc6fae2 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java @@ -18,14 +18,14 @@ package com.intellij.openapi.editor.colors; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.options.Scheme; -import com.intellij.openapi.util.JDOMExternalizable; +import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; -public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, TextAttributesScheme, Scheme { +public interface EditorColorsScheme extends Cloneable, TextAttributesScheme, Scheme { @NonNls String DEFAULT_SCHEME_NAME = "Default"; void setName(String name); @@ -90,4 +90,6 @@ public interface EditorColorsScheme extends Cloneable, JDOMExternalizable, TextA float getConsoleLineSpacing(); void setConsoleLineSpacing(float lineSpacing); + + void readExternal(Element parentNode); } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java index bd90843372ea..4940473bc740 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java @@ -18,7 +18,6 @@ package com.intellij.openapi.editor.colors.ex; import com.intellij.openapi.components.*; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; -import com.intellij.openapi.util.InvalidDataException; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -52,13 +51,8 @@ public class DefaultColorSchemesManager implements PersistentStateComponent CURR_VERSION) throw new InvalidDataException("Unsupported color scheme version: " + readVersion); - myVersion = readVersion; - String isDefaultScheme = node.getAttributeValue(DEFAULT_SCHEME_ATTR); - if (isDefaultScheme == null || !Boolean.parseBoolean(isDefaultScheme)) { - String parentSchemeName = node.getAttributeValue(PARENT_SCHEME_ATTR); - if (parentSchemeName == null) parentSchemeName = DEFAULT_SCHEME_NAME; - myParentScheme = myDefaultColorSchemesManager.getScheme(parentSchemeName); - } - - for (final Object o : node.getChildren()) { - Element childNode = (Element)o; - String childName = childNode.getName(); - if (OPTION_ELEMENT.equals(childName)) { - readSettings(childNode); - } - else if (EDITOR_FONT.equals(childName)) { - readFontSettings(childNode, myFontPreferences); - } - else if (CONSOLE_FONT.equals(childName)) { - readFontSettings(childNode, myConsoleFontPreferences); - } - else if (COLORS_ELEMENT.equals(childName)) { - readColors(childNode); - } - else if (ATTRIBUTES_ELEMENT.equals(childName)) { - readAttributes(childNode); - } - } - - if (myDeprecatedBackgroundColor != null) { - TextAttributes textAttributes = myAttributesMap.get(HighlighterColors.TEXT); - if (textAttributes == null) { - textAttributes = new TextAttributes(Color.black, myDeprecatedBackgroundColor, null, EffectType.BOXED, Font.PLAIN); - myAttributesMap.put(HighlighterColors.TEXT, textAttributes); - } - else { - textAttributes.setBackgroundColor(myDeprecatedBackgroundColor); - } - } - - if (myConsoleFontPreferences.getEffectiveFontFamilies().isEmpty()) { - myFontPreferences.copyTo(myConsoleFontPreferences); - } - - initFonts(); + if (!SCHEME_ELEMENT.equals(node.getName())) { + return; } + + setName(node.getAttributeValue(NAME_ATTR)); + int readVersion = Integer.parseInt(node.getAttributeValue(VERSION_ATTR, "0")); + if (readVersion > CURR_VERSION) { + throw new IllegalStateException("Unsupported color scheme version: " + readVersion); + } + + myVersion = readVersion; + String isDefaultScheme = node.getAttributeValue(DEFAULT_SCHEME_ATTR); + if (isDefaultScheme == null || !Boolean.parseBoolean(isDefaultScheme)) { + myParentScheme = DefaultColorSchemesManager.getInstance().getScheme(node.getAttributeValue(PARENT_SCHEME_ATTR, DEFAULT_SCHEME_NAME)); + } + + for (final Object o : node.getChildren()) { + Element childNode = (Element)o; + String childName = childNode.getName(); + if (OPTION_ELEMENT.equals(childName)) { + readSettings(childNode); + } + else if (EDITOR_FONT.equals(childName)) { + readFontSettings(childNode, myFontPreferences); + } + else if (CONSOLE_FONT.equals(childName)) { + readFontSettings(childNode, myConsoleFontPreferences); + } + else if (COLORS_ELEMENT.equals(childName)) { + readColors(childNode); + } + else if (ATTRIBUTES_ELEMENT.equals(childName)) { + readAttributes(childNode); + } + } + + if (myDeprecatedBackgroundColor != null) { + TextAttributes textAttributes = myAttributesMap.get(HighlighterColors.TEXT); + if (textAttributes == null) { + textAttributes = new TextAttributes(Color.black, myDeprecatedBackgroundColor, null, EffectType.BOXED, Font.PLAIN); + myAttributesMap.put(HighlighterColors.TEXT, textAttributes); + } + else { + textAttributes.setBackgroundColor(myDeprecatedBackgroundColor); + } + } + + if (myConsoleFontPreferences.getEffectiveFontFamilies().isEmpty()) { + myFontPreferences.copyTo(myConsoleFontPreferences); + } + + initFonts(); } - protected void readAttributes(Element childNode) throws InvalidDataException { - for (final Object o : childNode.getChildren(OPTION_ELEMENT)) { - Element e = (Element)o; - String key = e.getAttributeValue(NAME_ATTR); - TextAttributesKey name = TextAttributesKey.find(key); - Element value = e.getChild(VALUE_ELEMENT); - TextAttributes attr = new TextAttributes(value); + protected void readAttributes(@NotNull Element childNode) { + for (Element e : childNode.getChildren(OPTION_ELEMENT)) { + TextAttributesKey name = TextAttributesKey.find(e.getAttributeValue(NAME_ATTR)); + TextAttributes attr = new TextAttributes(e.getChild(VALUE_ELEMENT)); myAttributesMap.put(name, attr); migrateErrorStripeColorFrom45(name, attr); } @@ -446,7 +440,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { return value == null ? e.getAttributeValue(VALUE_ELEMENT) : value; } - @Override public void writeExternal(Element parentNode) throws WriteExternalException { parentNode.setAttribute(NAME_ATTR, getName()); parentNode.setAttribute(VERSION_ATTR, Integer.toString(myVersion)); @@ -545,9 +538,8 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { } } - private boolean haveToWrite(final TextAttributesKey key, final TextAttributes value, final TextAttributes defaultAttribute) { - if (key.getFallbackAttributeKey() != null && value.isFallbackEnabled()) return false; - return !value.equals(defaultAttribute); + private static boolean haveToWrite(final TextAttributesKey key, final TextAttributes value, final TextAttributes defaultAttribute) { + return !(key.getFallbackAttributeKey() != null && value.isFallbackEnabled()) && !value.equals(defaultAttribute); } private void writeAttributes(Element attrElements) throws WriteExternalException { diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java index 7c907d1c607b..31ab7469b217 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java @@ -22,9 +22,7 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorFontType; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.util.InvalidDataException; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,8 +32,8 @@ import java.awt.*; public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnlyColorsScheme { private String myName; - public DefaultColorsScheme(DefaultColorSchemesManager defaultColorSchemesManager) { - super(null, defaultColorSchemesManager); + public DefaultColorsScheme() { + super(null); } @Override @@ -62,7 +60,7 @@ public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnl } @Override - public void readExternal(Element parentNode) throws InvalidDataException { + public void readExternal(Element parentNode) { super.readExternal(parentNode); myName = parentNode.getAttributeValue(NAME_ATTR); } @@ -87,10 +85,9 @@ public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnl @Override public Object clone() { - EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(this, myDefaultColorSchemesManager); + EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(this); copyTo(newScheme); newScheme.setName(DEFAULT_SCHEME_NAME); return newScheme; } - } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java index 1fc6e1fa4f06..16c3592092a2 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImpl.java @@ -18,7 +18,6 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.ExternalInfo; import com.intellij.openapi.options.ExternalizableScheme; @@ -34,8 +33,8 @@ import java.awt.*; public class EditorColorsSchemeImpl extends AbstractColorsScheme implements ExternalizableScheme { private final ExternalInfo myExternalInfo = new ExternalInfo(); - public EditorColorsSchemeImpl(EditorColorsScheme parentScheme, DefaultColorSchemesManager defaultColorSchemesManager) { - super(parentScheme, defaultColorSchemesManager); + public EditorColorsSchemeImpl(EditorColorsScheme parentScheme) { + super(parentScheme); } @Override @@ -69,7 +68,6 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte return myParentScheme.getAttributes(key); } - public boolean containsKey(TextAttributesKey key) { return myAttributesMap.containsKey(key); } @@ -87,7 +85,7 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte @Override public Object clone() { - EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(myParentScheme, DefaultColorSchemesManager.getInstance()); + EditorColorsSchemeImpl newScheme = new EditorColorsSchemeImpl(myParentScheme); copyTo(newScheme); newScheme.setName(getName()); return newScheme; diff --git a/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java b/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java index e9e72103f612..5eb526877ba6 100644 --- a/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java +++ b/platform/lang-api/src/com/intellij/usageView/UsageTreeColorsScheme.java @@ -20,7 +20,6 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.EditorColorsUtil; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.ui.UIUtil; @@ -51,10 +50,9 @@ public class UsageTreeColorsScheme implements NamedComponent, JDOMExternalizable } @Override - public void readExternal(Element element) throws InvalidDataException { + public void readExternal(Element element) { if (myColorsScheme == null) { - EditorColorsScheme scheme = EditorColorsUtil.getColorSchemeForBackground(UIUtil.getTreeTextBackground()); - myColorsScheme = (EditorColorsScheme)scheme.clone(); + myColorsScheme = (EditorColorsScheme)EditorColorsUtil.getColorSchemeForBackground(UIUtil.getTreeTextBackground()).clone(); } myColorsScheme.readExternal(element); } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index dff0a5c4eac8..bda2aab689ba 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -32,7 +32,6 @@ import com.intellij.openapi.editor.colors.ColorKey; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl; import com.intellij.openapi.editor.colors.impl.ReadOnlyColorsScheme; @@ -990,7 +989,8 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract private boolean myIsNew = false; private MyColorScheme(@NotNull EditorColorsScheme parentScheme) { - super(parentScheme, DefaultColorSchemesManager.getInstance()); + super(parentScheme); + parentScheme.getFontPreferences().copyTo(getFontPreferences()); setLineSpacing(parentScheme.getLineSpacing()); diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java index 4547726a4834..9dda8602f086 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java @@ -20,7 +20,6 @@ import com.intellij.ide.actions.QuickSwitchSchemeAction; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.BundledQuickListsProvider; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ex.DecodeDefaultsUtil; import com.intellij.openapi.components.ExportableApplicationComponent; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.StoragePathMacros; @@ -31,12 +30,12 @@ import com.intellij.openapi.options.SchemesManagerFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.JDOMUtil; import com.intellij.util.PathUtilRt; +import com.intellij.util.ThrowableConvertor; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import java.io.File; -import java.io.InputStream; import java.util.Collection; import java.util.Set; @@ -101,25 +100,17 @@ public class QuickListsManager implements ExportableApplicationComponent { @Override public void initComponent() { for (BundledQuickListsProvider provider : BundledQuickListsProvider.EP_NAME.getExtensions()) { - for (String path : provider.getBundledListsRelativePaths()) { - try { - InputStream inputStream = DecodeDefaultsUtil.getDefaultsInputStream(provider, path); - if (inputStream == null) { - // Error shouldn't occur during this operation thus we report error instead of info - LOG.error("Cannot read quick list from " + path); - } - else { - Element element = JDOMUtil.load(inputStream); + for (final String path : provider.getBundledListsRelativePaths()) { + mySchemesManager.loadBundledScheme(path, provider, new ThrowableConvertor() { + @Override + public QuickList convert(Element element) throws Throwable { QuickList item = createItem(element); item.getExternalInfo().setHash(JDOMUtil.getTreeHash(element, true)); item.getExternalInfo().setPreviouslySavedName(item.getName()); item.getExternalInfo().setCurrentFileName(PathUtilRt.getFileName(path)); - mySchemesManager.addNewScheme(item, false); + return item; } - } - catch (Exception e) { - LOG.error("Cannot read quick list from " + path + ": " + e.getMessage(), e); - } + }); } } mySchemesManager.loadSchemes(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java index 1089d5e54e3e..01fe0814f2c3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java @@ -18,8 +18,6 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -145,11 +143,7 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { } @Override - public void readExternal(Element element) throws InvalidDataException { - } - - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void readExternal(Element element) { } @NotNull @@ -203,5 +197,4 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { public void setConsoleLineSpacing(float lineSpacing) { myDelegate.setConsoleLineSpacing(lineSpacing); } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java index 1421aef3e99c..e4a8a78c5698 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java @@ -13,21 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * @author Yura Cangea - */ package com.intellij.openapi.editor.colors.impl; import com.intellij.ide.WelcomeWizardUtil; import com.intellij.ide.ui.LafManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.components.ExportableComponent; -import com.intellij.openapi.components.NamedComponent; -import com.intellij.openapi.components.RoamingType; -import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.colors.EditorColorsListener; @@ -36,42 +28,47 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.options.*; -import com.intellij.openapi.util.*; +import com.intellij.openapi.options.BaseSchemeProcessor; +import com.intellij.openapi.options.Scheme; +import com.intellij.openapi.options.SchemesManager; +import com.intellij.openapi.options.SchemesManagerFactory; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.EventDispatcher; +import com.intellij.util.ThrowableConvertor; +import com.intellij.util.io.URLUtil; import com.intellij.util.ui.UIUtil; +import com.intellij.util.xmlb.annotations.OptionTag; import org.jdom.Element; -import org.jdom.JDOMException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.net.URL; import java.util.Arrays; import java.util.Comparator; import java.util.List; -public class EditorColorsManagerImpl extends EditorColorsManager implements NamedJDOMExternalizable, ExportableComponent, NamedComponent { +@State( + name = "EditorColorsManagerImpl", + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/colors.scheme.xml"), + additionalExportFile = EditorColorsManagerImpl.FILE_SPEC +) +public class EditorColorsManagerImpl extends EditorColorsManager implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance(EditorColorsManagerImpl.class); - private final EventDispatcher myListeners = EventDispatcher.create(EditorColorsListener.class); - - @NonNls private static final String NODE_NAME = "global_color_scheme"; @NonNls private static final String SCHEME_NODE_NAME = "scheme"; private static final String DEFAULT_NAME = "Default"; - private String myGlobalSchemeName; - public boolean USE_ONLY_MONOSPACED_FONTS = true; + private final EventDispatcher myListeners = EventDispatcher.create(EditorColorsListener.class); + private final DefaultColorSchemesManager myDefaultColorSchemesManager; private final SchemesManager mySchemesManager; - @NonNls private static final String NAME_ATTR = "name"; - private static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/colors"; - @NonNls - private static final String FILE_EXT = ".icls"; + static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/colors"; + + private State myState = new State(); public EditorColorsManagerImpl(DefaultColorSchemesManager defaultColorSchemesManager, SchemesManagerFactory schemesManagerFactory) { myDefaultColorSchemesManager = defaultColorSchemesManager; @@ -79,8 +76,10 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, new BaseSchemeProcessor() { @NotNull @Override - public EditorColorsSchemeImpl readScheme(@NotNull Element element) throws InvalidDataException { - return loadSchemeFromDocument(element, true); + public EditorColorsSchemeImpl readScheme(@NotNull Element element) { + EditorColorsSchemeImpl scheme = new EditorColorsSchemeImpl(null); + scheme.readExternal(element); + return scheme; } @Override @@ -93,7 +92,6 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name LOG.error(e); return null; } - return root; } @@ -109,9 +107,10 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } @NotNull + @NonNls @Override public String getSchemeExtension() { - return FILE_EXT; + return ".icls"; } @Override @@ -124,7 +123,14 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name // Load default schemes from providers if (!isUnitTestOrHeadlessMode()) { - loadSchemesFromBeans(); + for (BundledColorSchemeEP ep : BundledColorSchemeEP.EP_NAME.getExtensions()) { + mySchemesManager.loadBundledScheme(ep.path + ".xml", ep, new ThrowableConvertor() { + @Override + public EditorColorsScheme convert(Element element) throws Throwable { + return new ReadOnlyColorsSchemeImpl(element); + } + }); + } } mySchemesManager.loadSchemes(); @@ -137,8 +143,22 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name scheme = getScheme(wizardEditorScheme); LOG.assertTrue(scheme != null, "Wizard scheme " + wizardEditorScheme + " not found"); } - if (scheme == null) scheme = myDefaultColorSchemesManager.getAllSchemes()[0]; - setGlobalSchemeInner(scheme); + setGlobalSchemeInner(scheme == null ? getDefaultScheme() : scheme); + } + + static class ReadOnlyColorsSchemeImpl extends EditorColorsSchemeImpl implements ReadOnlyColorsScheme { + public ReadOnlyColorsSchemeImpl(@NotNull Element element) { + super(null); + + readExternal(element); + } + } + + static class State { + public boolean USE_ONLY_MONOSPACED_FONTS = true; + + @OptionTag(tag = "global_color_scheme", nameAttribute = "", valueAttribute = "name") + public String colorScheme; } private static boolean isUnitTestOrHeadlessMode() { @@ -150,29 +170,12 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name // It is reasonable to fetch attributes from Default color scheme. Otherwise if we launch IDE and then // try switch from custom colors scheme (e.g. with dark background) to default one. Editor will show // incorrect highlighting with "traces" of color scheme which was active during IDE startup. - final EditorColorsScheme defaultColorScheme = getScheme(dark ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME); - return defaultColorScheme.getAttributes(key); - } - - private void loadSchemesFromBeans() { - for (BundledColorSchemeEP schemeEP : Extensions.getExtensions(BundledColorSchemeEP.EP_NAME)) { - String fileName = schemeEP.path + ".xml"; - InputStream stream = schemeEP.getLoaderForClass().getResourceAsStream(fileName); - try { - EditorColorsSchemeImpl scheme = loadSchemeFromStream(fileName, stream); - if (scheme != null) { - mySchemesManager.addNewScheme(scheme, false); - } - } - catch (final Exception e) { - LOG.error("Cannot read scheme from " + fileName + ": " + e.getLocalizedMessage(), e); - } - } + return getScheme(dark ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME).getAttributes(key); } private void loadAdditionalTextAttributes() { for (AdditionalTextAttributesEP attributesEP : AdditionalTextAttributesEP.EP_NAME.getExtensions()) { - final EditorColorsScheme editorColorsScheme = mySchemesManager.findSchemeByName(attributesEP.scheme); + EditorColorsScheme editorColorsScheme = mySchemesManager.findSchemeByName(attributesEP.scheme); if (editorColorsScheme == null) { if (!isUnitTestOrHeadlessMode()) { LOG.warn("Cannot find scheme: " + attributesEP.scheme + " from plugin: " + attributesEP.getPluginDescriptor().getPluginId()); @@ -180,53 +183,19 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name continue; } try { - InputStream inputStream = attributesEP.getLoaderForClass().getResourceAsStream(attributesEP.file); - ((AbstractColorsScheme)editorColorsScheme).readAttributes(JDOMUtil.load(inputStream)); + URL resource = attributesEP.getLoaderForClass().getResource(attributesEP.file); + assert resource != null; + ((AbstractColorsScheme)editorColorsScheme).readAttributes(JDOMUtil.load(URLUtil.openStream(resource))); } - catch (Exception e1) { - LOG.error(e1); + catch (Exception e) { + LOG.error(e); } } } - private static EditorColorsSchemeImpl loadSchemeFromStream(String schemePath, InputStream inputStream) - throws IOException, JDOMException, InvalidDataException { - if (inputStream == null) { - // Error shouldn't occur during this operation - // thus we report error instead of info - LOG.error("Cannot read scheme from " + schemePath); - return null; - } - - Element element; - try { - element = JDOMUtil.load(inputStream); - } - catch (JDOMException e) { - LOG.info("Error reading scheme from " + schemePath + ": " + e.getLocalizedMessage()); - throw e; - } - return loadSchemeFromDocument(element, false); - } - - @NotNull - private static EditorColorsSchemeImpl loadSchemeFromDocument(@NotNull Element element, boolean isEditable) throws InvalidDataException { - if (!SCHEME_NODE_NAME.equals(element.getName())) { - throw new InvalidDataException(); - } - - final EditorColorsSchemeImpl scheme = isEditable - // editable scheme - ? new EditorColorsSchemeImpl(null, DefaultColorSchemesManager.getInstance()) - //not editable scheme - : new ReadOnlyColorsSchemeImpl(null, DefaultColorSchemesManager.getInstance()); - scheme.readExternal(element); - return scheme; - } - @Override public void addColorsScheme(@NotNull EditorColorsScheme scheme) { - if (!isDefaultScheme(scheme) && scheme.getName().trim().length() > 0) { + if (!isDefaultScheme(scheme) && !StringUtil.isEmpty(scheme.getName())) { mySchemesManager.addNewScheme(scheme, true); } } @@ -238,8 +207,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } private void addDefaultSchemes() { - DefaultColorsScheme[] allDefaultSchemes = myDefaultColorSchemesManager.getAllSchemes(); - for (DefaultColorsScheme defaultScheme : allDefaultSchemes) { + for (DefaultColorsScheme defaultScheme : myDefaultColorSchemesManager.getAllSchemes()) { mySchemesManager.addNewScheme(defaultScheme, true); } } @@ -277,18 +245,15 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } @NotNull - private static DefaultColorsScheme getDefaultScheme() { - return DefaultColorSchemesManager.getInstance().getAllSchemes()[0]; + private DefaultColorsScheme getDefaultScheme() { + return myDefaultColorSchemesManager.getAllSchemes()[0]; } @NotNull @Override public EditorColorsScheme getGlobalScheme() { - final EditorColorsScheme scheme = mySchemesManager.getCurrentScheme(); - if (scheme == null) { - return getDefaultScheme(); - } - return scheme; + EditorColorsScheme scheme = mySchemesManager.getCurrentScheme(); + return scheme == null ? getDefaultScheme() : scheme; } @Override @@ -300,20 +265,6 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name myListeners.getMulticaster().globalSchemeChange(scheme); } - private static File getColorsDir(boolean create) { - @NonNls String directoryPath = PathManager.getConfigPath() + File.separator + "colors"; - File directory = new File(directoryPath); - if (!directory.exists()) { - if (!create) return null; - if (!directory.mkdir()) { - LOG.error("Cannot create directory: " + directory.getAbsolutePath()); - return null; - } - } - return directory; - } - - @Override public void addEditorColorsListener(@NotNull EditorColorsListener listener) { myListeners.addListener(listener); @@ -330,56 +281,29 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name } @Override - public void setUseOnlyMonospacedFonts(boolean b) { - USE_ONLY_MONOSPACED_FONTS = b; + public void setUseOnlyMonospacedFonts(boolean value) { + myState.USE_ONLY_MONOSPACED_FONTS = value; } @Override public boolean isUseOnlyMonospacedFonts() { - return USE_ONLY_MONOSPACED_FONTS; + return myState.USE_ONLY_MONOSPACED_FONTS; } + @Nullable @Override - public String getExternalFileName() { - return "colors.scheme"; - } - - @Override - @NotNull - public File[] getExportFiles() { - return new File[]{getColorsDir(true), PathManager.getOptionsFile(this)}; - } - - @Override - @NotNull - public String getPresentableName() { - return OptionsBundle.message("options.color.schemes.presentable.name"); - } - - @Override - public void readExternal(Element parentNode) throws InvalidDataException { - DefaultJDOMExternalizer.readExternal(this, parentNode); - Element element = parentNode.getChild(NODE_NAME); - if (element != null) { - String name = element.getAttributeValue(NAME_ATTR); - if (StringUtil.isNotEmpty(name)) { - myGlobalSchemeName = name; - } - } - - EditorColorsScheme globalScheme = - myGlobalSchemeName != null ? mySchemesManager.findSchemeByName(myGlobalSchemeName) : myDefaultColorSchemesManager.getAllSchemes()[0]; - setGlobalSchemeInner(globalScheme); - } - - @Override - public void writeExternal(Element parentNode) throws WriteExternalException { - DefaultJDOMExternalizer.writeExternal(this, parentNode); + public State getState() { if (mySchemesManager.getCurrentScheme() != null) { - Element element = new Element(NODE_NAME); - element.setAttribute(NAME_ATTR, mySchemesManager.getCurrentScheme().getName()); - parentNode.addContent(element); + String name = mySchemesManager.getCurrentScheme().getName(); + myState.colorScheme = "Default".equals(name) ? null : name; } + return myState; + } + + @Override + public void loadState(State state) { + myState = state; + setGlobalSchemeInner(myState.colorScheme == null ? getDefaultScheme() : mySchemesManager.findSchemeByName(myState.colorScheme)); } @Override @@ -387,13 +311,8 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name return scheme instanceof DefaultColorsScheme; } + @TestOnly public SchemesManager getSchemesManager() { return mySchemesManager; } - - @Override - @NotNull - public String getComponentName() { - return "EditorColorsManagerImpl"; - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java deleted file mode 100644 index f7a777edb96f..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/ReadOnlyColorsSchemeImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.editor.colors.impl; - -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; - -/** - * @author Roman Chernyatchik - */ -public class ReadOnlyColorsSchemeImpl extends EditorColorsSchemeImpl implements ReadOnlyColorsScheme { - public ReadOnlyColorsSchemeImpl(final EditorColorsScheme parenScheme, - final DefaultColorSchemesManager defaultColorSchemesManager) { - super(parenScheme, defaultColorSchemesManager); - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java index 58bf8e6ecb64..03714165fa24 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java @@ -18,6 +18,7 @@ package com.intellij.openapi.options; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.DecodeDefaultsUtil; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.StateStorageException; @@ -27,6 +28,7 @@ import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.components.impl.stores.StreamProvider; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.DocumentRunnable; +import com.intellij.openapi.extensions.AbstractExtensionPointBean; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.InvalidDataException; @@ -41,7 +43,9 @@ import com.intellij.openapi.vfs.VirtualFileAdapter; import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; import com.intellij.util.SmartList; +import com.intellij.util.ThrowableConvertor; import com.intellij.util.containers.ContainerUtilRt; +import com.intellij.util.io.URLUtil; import com.intellij.util.text.UniqueNameGenerator; import gnu.trove.THashSet; import org.jdom.Document; @@ -55,6 +59,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URL; import java.util.*; public class SchemesManagerImpl extends AbstractSchemesManager { @@ -164,6 +169,23 @@ public class SchemesManagerImpl convertor) { + try { + URL url = requestor instanceof AbstractExtensionPointBean + ? (((AbstractExtensionPointBean)requestor).getLoaderForClass().getResource(resourceName)) + : DecodeDefaultsUtil.getDefaults(requestor, resourceName); + if (url == null) { + // Error shouldn't occur during this operation thus we report error instead of info + LOG.error("Cannot read scheme from " + resourceName); + return; + } + addNewScheme(convertor.convert(JDOMUtil.load(URLUtil.openStream(url))), false); + } + catch (Throwable e) { + LOG.error("Cannot read scheme from " + resourceName, e); + } + } + private boolean isMy(@NotNull VirtualFileEvent event) { return StringUtilRt.endsWithIgnoreCase(event.getFile().getNameSequence(), mySchemeExtension); } diff --git a/platform/platform-resources-en/src/messages/OptionsBundle.properties b/platform/platform-resources-en/src/messages/OptionsBundle.properties index 761cb2400667..4972ee89de88 100644 --- a/platform/platform-resources-en/src/messages/OptionsBundle.properties +++ b/platform/platform-resources-en/src/messages/OptionsBundle.properties @@ -252,7 +252,6 @@ project.file.read.only.error.message=The project file is read-only.\nThe setting template.project.settings.display.name=Template Project Settings #0 - project name project.settings.display.name=Project Settings [{0}] -options.color.schemes.presentable.name=Color schemes options.java.attribute.descriptor.weak.warning=Weak Warning options.java.attribute.descriptor.server.problems=Problem from server options.java.attribute.descriptor.server.duplicate=Duplicate from server @@ -315,4 +314,5 @@ exportable.CodeStyleSchemeSettings.presentable.name=Code Style exportable.InspectionProfileManager.presentable.name=Inspection profiles exportable.TodoConfiguration.presentable.name=Todo exportable.UISettings.presentable.name=UI Settings -exportable.FileTypeManager.presentable.name=File types \ No newline at end of file +exportable.FileTypeManager.presentable.name=File types +exportable.EditorColorsManager.presentable.name=Color schemes \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index 675f6715f201..348dc0d94bfc 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.testFramework.PlatformTestCase; import org.jdom.Element; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; @@ -28,12 +29,14 @@ import java.io.StringWriter; import java.util.Arrays; import java.util.Collections; -import static com.intellij.openapi.editor.colors.FontPreferencesTest.checkState; -import static com.intellij.openapi.editor.colors.FontPreferencesTest.getAnotherExistingNonDefaultFontName; -import static com.intellij.openapi.editor.colors.FontPreferencesTest.getExistingNonDefaultFontName; +import static com.intellij.openapi.editor.colors.FontPreferencesTest.*; public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase { - EditorColorsSchemeImpl myScheme = new EditorColorsSchemeImpl(null, null); + EditorColorsSchemeImpl myScheme = new EditorColorsSchemeImpl(null); + + static { + PlatformTestCase.initPlatformLangPrefix(); + } public void testDefaults() { checkState(myScheme.getFontPreferences(), @@ -173,7 +176,7 @@ public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase EditorColorsScheme editorColorsScheme = (EditorColorsScheme)defaultScheme.clone(); editorColorsScheme.setName("test"); Element root = new Element("scheme"); - editorColorsScheme.writeExternal(root); + ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); root.removeChildren("option"); // Remove font options assertXmlOutputEquals("", root); } @@ -183,7 +186,7 @@ public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase EditorColorsScheme editorColorsScheme = (EditorColorsScheme)darculaScheme.clone(); editorColorsScheme.setName("test"); Element root = new Element("scheme"); - editorColorsScheme.writeExternal(root); + ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); root.removeChildren("option"); // Remove font options assertXmlOutputEquals("", root); } diff --git a/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java b/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java index 370465f3f994..967beebc2078 100644 --- a/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java +++ b/platform/testFramework/src/com/intellij/testFramework/MockSchemesManagerFactory.java @@ -5,17 +5,18 @@ import com.intellij.openapi.options.*; import org.jetbrains.annotations.NotNull; public class MockSchemesManagerFactory extends SchemesManagerFactory { + private static final SchemesManager EMPTY = new EmptySchemesManager(); + @NotNull @Override public SchemesManager createSchemesManager(@NotNull String fileSpec, @NotNull SchemeProcessor processor, @NotNull RoamingType roamingType) { //noinspection unchecked - return SchemesManager.EMPTY; + return EMPTY; } @Override public void updateConfigFilesFromStreamProviders() { - } } diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java index f388d9d931f6..0f19c66153e5 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java @@ -27,8 +27,6 @@ import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.options.FontSize; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.containers.HashMap; import com.jediterm.pty.PtyProcessTtyConnector; import com.jediterm.terminal.TerminalColor; @@ -401,11 +399,7 @@ public class JBTerminalSystemSettingsProvider extends DefaultTabbedSettingsProvi } @Override - public void readExternal(Element element) throws InvalidDataException { - } - - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void readExternal(Element element) { } public void updateGlobalScheme(EditorColorsScheme scheme) { From 3a32a16c00a100ef23658fe295b13a67c3e787f6 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 19 Feb 2015 20:55:32 +0100 Subject: [PATCH 088/231] remove wrong final modifier from groovy code --- .../plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy | 2 +- .../refactoring/changeSignature/SimpleParameterGen.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy index bdf180c6011c..1803989b429d 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy @@ -84,7 +84,7 @@ class WarModelBuilderImpl implements ModelBuilderService { } final String relativePath = resolver.destPath.pathString - final def sourcePaths + def sourcePaths if (resolver.metaClass.respondsTo(resolver, 'getSourcePaths')) { sourcePaths = resolver.getSourcePaths() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/SimpleParameterGen.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/SimpleParameterGen.groovy index f7f6c1b11b8f..09e7047566c0 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/SimpleParameterGen.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/SimpleParameterGen.groovy @@ -44,7 +44,7 @@ class SimpleParameterGen implements ChangeSignatureTestCase.GenParams { final SimpleInfo sim = myInfos[i]; int oldIndex = sim.myOldIndex; - final GrParameterInfo info; + GrParameterInfo info; String name = null; String defInitializer = null; PsiType type = null; From f8c698fdc1cfb0150d2ef721453935ba6cc744d7 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 20 Feb 2015 19:31:46 +0300 Subject: [PATCH 089/231] source searcher: compilation fix --- .../src/com/intellij/jarFinder/SourceSearcher.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java index 0b97e631148b..3533f1a4bb21 100644 --- a/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java +++ b/java/java-impl/src/com/intellij/jarFinder/SourceSearcher.java @@ -84,7 +84,11 @@ public abstract class SourceSearcher { } } finally { - StreamUtil.closeStream(jarFile); + try { + jarFile.close(); + } + catch (IOException ignore) { + } } } catch (IOException ignore) { From c613d3970fdcd8869f197f61fe59bda5da3a1e38 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Feb 2015 12:03:19 +0100 Subject: [PATCH 090/231] DocumentImpl: a faster check for no assertions --- .../src/com/intellij/openapi/editor/impl/DocumentImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 5543c430f361..a7f54fc9c8dd 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -770,10 +770,10 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { } private void assertInsideCommand() { + if (!myAssertThreading) return; CommandProcessor commandProcessor = CommandProcessor.getInstance(); if (!commandProcessor.isUndoTransparentActionInProgress() && - commandProcessor.getCurrentCommand() == null && - myAssertThreading) { + commandProcessor.getCurrentCommand() == null) { throw new IncorrectOperationException("Must not change document outside command or undo-transparent action. See com.intellij.openapi.command.WriteCommandAction or com.intellij.openapi.command.CommandProcessor"); } } From 4f2ff641cdcc2761311e6f7062509ff9db54d951 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Feb 2015 17:20:59 +0100 Subject: [PATCH 091/231] completion-robust LightFieldBuilder.isEquivalentTo (https://devnet.jetbrains.com/message/5535850) --- .../com/intellij/psi/impl/light/LightFieldBuilder.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java index 72256079a0fd..87df5dcb049d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java @@ -83,4 +83,14 @@ public class LightFieldBuilder extends LightVariableBuilder i public PsiClass getContainingClass() { return myContainingClass; } + + @Override + public boolean isEquivalentTo(PsiElement another) { + if (!(another instanceof PsiField)) return false; + if (!((PsiField)another).getName().equals(getName())) return false; + if (hasModifierProperty(PsiModifier.STATIC) != ((PsiField)another).hasModifierProperty(PsiModifier.STATIC)) return false; + final PsiClass containingClass = getContainingClass(); + final PsiClass anotherClass = ((PsiField)another).getContainingClass(); + return containingClass == null && anotherClass == null || getManager().areElementsEquivalent(containingClass, anotherClass); + } } From 16c5d264d8b03e98cddecc8c0a26da848a8eaa2f Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Feb 2015 17:24:30 +0100 Subject: [PATCH 092/231] IndexNotReadyException.java, util -> core-api --- .../intellij/openapi/project/IndexNotReadyException.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename platform/{util => core-api}/src/com/intellij/openapi/project/IndexNotReadyException.java (82%) diff --git a/platform/util/src/com/intellij/openapi/project/IndexNotReadyException.java b/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java similarity index 82% rename from platform/util/src/com/intellij/openapi/project/IndexNotReadyException.java rename to platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java index 80ef38138b89..3b5ba9ecf996 100644 --- a/platform/util/src/com/intellij/openapi/project/IndexNotReadyException.java +++ b/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java @@ -18,14 +18,14 @@ package com.intellij.openapi.project; /** * Thrown on accessing indices in dumb mode. Possible fixes: *
  • if {@link com.intellij.openapi.actionSystem.AnAction#actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent)} is in stack trace, - * consider making the action not implement {@link com.intellij.openapi.project.DumbAware}. + * consider making the action not implement {@link DumbAware}. *
  • if this access is performed from some invokeLater activity, consider replacing it with - * {@link com.intellij.openapi.project.DumbService#smartInvokeLater(Runnable)} + * {@link DumbService#smartInvokeLater(Runnable)} *
  • otherwise, add {@link DumbService#isDumb()} checks where necessary * * @author peter - * @see com.intellij.openapi.project.DumbService - * @see com.intellij.openapi.project.DumbAware + * @see DumbService + * @see DumbAware */ public class IndexNotReadyException extends RuntimeException { From f8d95121db9376111d830a567490341804b79d21 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Feb 2015 17:37:49 +0100 Subject: [PATCH 093/231] expand INRE javadoc to include new coping strategies --- .../project/IndexNotReadyException.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java b/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java index 3b5ba9ecf996..b8bd9641ab31 100644 --- a/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java +++ b/platform/core-api/src/com/intellij/openapi/project/IndexNotReadyException.java @@ -15,13 +15,32 @@ */ package com.intellij.openapi.project; +import com.intellij.openapi.util.Computable; + /** - * Thrown on accessing indices in dumb mode. Possible fixes: - *
  • if {@link com.intellij.openapi.actionSystem.AnAction#actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent)} is in stack trace, + * Thrown on accessing indices when they're not ready, in so-called dumb mode. Possible fixes: + *
      + *
    • If {@link com.intellij.openapi.actionSystem.AnAction#actionPerformed(com.intellij.openapi.actionSystem.AnActionEvent)} is in stack trace, * consider making the action not implement {@link DumbAware}. - *
    • if this access is performed from some invokeLater activity, consider replacing it with - * {@link DumbService#smartInvokeLater(Runnable)} - *
    • otherwise, add {@link DumbService#isDumb()} checks where necessary + * + *
    • A {@link DumbAware} action, having got this exception, may just notify the user that the requested activity is not possible while + * indexing is in progress. It can be done via a dialog (see {@link com.intellij.openapi.ui.Messages}) or a status bar balloon + * (see {@link DumbService#showDumbModeNotification(String)}, {@link com.intellij.openapi.actionSystem.ex.ActionUtil#showDumbModeWarning(com.intellij.openapi.actionSystem.AnActionEvent...)}). + * + *
    • If index access is performed from some non-urgent invokeLater activity, consider replacing it with + * {@link DumbService#smartInvokeLater(Runnable)}. Note that this 'later' can be very late, several minutes may pass. So if that code + * involves user interaction, {@link DumbService#smartInvokeLater(Runnable)} should probably not be used to avoid dialogs popping out of the blue. + * + *
    • If it's a non-urgent background process (e.g. compilation, usage search), consider replacing topmost read-action with + * {@link DumbService#runReadActionInSmartMode(Computable)}. + * + *
    • If the exception comes from within Java's findClass call, and the IDE is currently performing a user-initiated action or a + * task when skipping findClass would lead to very negative consequences (e.g. not stopping at a breakpoint), then it might be possible + * to avoid index query by using alternative resolve (and findClass) strategy, which is significantly slower and might return null. To do this, + * use {@link DumbService#setAlternativeResolveEnabled(boolean)}. + * + *
    • It's preferable to avoid the exception entirely by adding {@link DumbService#isDumb()} checks where necessary. + *
    * * @author peter * @see DumbService From 4901d7676c323f4296e0ecd67deb4afd768a06d8 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 20 Feb 2015 18:15:52 +0100 Subject: [PATCH 094/231] register MethodsSuperSearch in JavaCoreEnvironment --- .../com/intellij/core/JavaCoreApplicationEnvironment.java | 7 ++++++- .../com/intellij/psi/impl/search/MethodSuperSearcher.java | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) rename java/{java-indexing-impl => java-psi-impl}/src/com/intellij/psi/impl/search/MethodSuperSearcher.java (99%) diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java index 8311ec0b199a..e4a4add097d0 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -41,10 +41,13 @@ import com.intellij.psi.impl.LanguageConstantExpressionEvaluator; import com.intellij.psi.impl.PsiExpressionEvaluator; import com.intellij.psi.impl.compiled.ClassFileStubBuilder; import com.intellij.psi.impl.file.PsiPackageImplementationHelper; +import com.intellij.psi.impl.search.MethodSuperSearcher; import com.intellij.psi.impl.source.tree.CoreJavaASTFactory; import com.intellij.psi.impl.source.tree.PlainTextASTFactory; import com.intellij.psi.presentation.java.*; +import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.stubs.BinaryFileStubBuilders; +import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; /** @@ -98,6 +101,8 @@ public class JavaCoreApplicationEnvironment extends CoreApplicationEnvironment { } }); + registerApplicationExtensionPoint(SuperMethodsSearch.EP_NAME, QueryExecutor.class); + addExtension(SuperMethodsSearch.EP_NAME, new MethodSuperSearcher()); } @SuppressWarnings("MethodMayBeStatic") // overridden in upsource diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java b/java/java-psi-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java similarity index 99% rename from java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java rename to java/java-psi-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java index acb5faae4947..d19b54fdd75c 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/search/MethodSuperSearcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. From ca120c0cb9a0672145f517fe0cc2b214365d7600 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 20 Feb 2015 20:31:09 +0300 Subject: [PATCH 095/231] revert and a better fix for IDEA-136786 --- .../com/intellij/openapi/editor/colors/EditorFontType.java | 4 +++- .../com/intellij/execution/console/LanguageConsoleImpl.java | 2 +- .../src/com/intellij/execution/impl/ConsoleViewUtil.java | 6 +----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java index e98a742e5417..1ef7b91fa454 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorFontType.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.editor.colors; +import com.intellij.util.ObjectUtils; + import java.util.HashMap; import java.util.Map; @@ -37,6 +39,6 @@ public enum EditorFontType { } public static EditorFontType getConsoleType(EditorFontType fontType) { - return ourConsoleTypes.get(fontType); + return ObjectUtils.chooseNotNull(ourConsoleTypes.get(fontType), fontType); } } diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 52765bb5a990..60b7a652617a 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -166,7 +166,7 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons return getConsoleEditor().getContentComponent(); } - public void initComponents() { + private void initComponents() { setupComponents(); myPanel.add(myHistoryViewer.getComponent()); diff --git a/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java b/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java index 0880e395308f..150dff080fe5 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/ConsoleViewUtil.java @@ -126,11 +126,7 @@ public class ConsoleViewUtil { @Override public Font getFont(EditorFontType key) { - Font font = super.getFont(EditorFontType.getConsoleType(key)); - if (font == null) { - return super.getFont(key); - } - return font; + return super.getFont(EditorFontType.getConsoleType(key)); } @Override From 4a9d8ced6132db1a5de4148c4c0b0783d4868408 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 20 Feb 2015 19:42:58 +0100 Subject: [PATCH 096/231] WEB-15337 InvocationTargetException when add new html file in Meteor project while debugger is running --- .../com/intellij/xdebugger/XDebugProcess.java | 11 ++- .../xdebugger/impl/XDebugSessionImpl.java | 84 ++++++++++--------- 2 files changed, 55 insertions(+), 40 deletions(-) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java index ee949a2ae9ce..d7499346099f 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java @@ -30,6 +30,7 @@ import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; import com.intellij.xdebugger.ui.XDebugTabLayouter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; import javax.swing.event.HyperlinkListener; @@ -131,7 +132,15 @@ public abstract class XDebugProcess { * Stop debugging and dispose resources. * Do not call this method directly. Use {@link XDebugSession#stop} instead */ - public abstract void stop(); + public void stop() { + throw new AbstractMethodError(); + } + + @NotNull + public Promise stopAsync() { + stop(); + return Promise.DONE; + } /** * Resume execution. diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 6b172c5432be..b8abd9764511 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -48,6 +48,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.AppUIUtil; +import com.intellij.util.Consumer; import com.intellij.util.EventDispatcher; import com.intellij.util.SmartList; import com.intellij.util.containers.SmartHashSet; @@ -110,7 +111,7 @@ public class XDebugSessionImpl implements XDebugSession { private final EventDispatcher myDispatcher = EventDispatcher.create(XDebugSessionListener.class); private final Project myProject; private final @Nullable ExecutionEnvironment myEnvironment; - private boolean myStopped; + private final AtomicBoolean myStopped = new AtomicBoolean(); private boolean myPauseActionSupported; private final AtomicBoolean myShowTabOnSuspend; private final List myRestartActions = new SmartList(); @@ -840,51 +841,56 @@ public class XDebugSessionImpl implements XDebugSession { @Override public boolean isStopped() { - return myStopped; + return myStopped.get(); } private void stopImpl() { - if (myStopped) return; - - myDebugProcess.stop(); - if (!myProject.isDisposed()) { - myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess); + if (!myStopped.compareAndSet(false, true)) { + return; } - if (mySessionTab != null) { - ((XWatchesViewImpl)mySessionTab.getWatchesView()).updateSessionData(); - mySessionTab.detachFromSession(); - } - else if (myConsoleView != null) { - Disposer.dispose(myConsoleView); - } + myDebugProcess.stopAsync().done(new Consumer() { + @Override + public void consume(Void aVoid) { + if (!myProject.isDisposed()) { + myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess); + } - myTopFramePosition = null; - myCurrentExecutionStack = null; - myCurrentStackFrame = null; - mySuspendContext = null; - if (myDebuggerManager.getCurrentSession() == this) { - myDebuggerManager.updateExecutionPoint(null, false, null); - } - if (breakpointsInitialized) { - XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager(); - if (myBreakpointListener != null) { - breakpointManager.removeBreakpointListener(myBreakpointListener); + if (mySessionTab != null) { + ((XWatchesViewImpl)mySessionTab.getWatchesView()).updateSessionData(); + mySessionTab.detachFromSession(); + } + else if (myConsoleView != null) { + Disposer.dispose(myConsoleView); + } + + myTopFramePosition = null; + myCurrentExecutionStack = null; + myCurrentStackFrame = null; + mySuspendContext = null; + if (myDebuggerManager.getCurrentSession() == XDebugSessionImpl.this) { + myDebuggerManager.updateExecutionPoint(null, false, null); + } + if (breakpointsInitialized) { + XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager(); + if (myBreakpointListener != null) { + breakpointManager.removeBreakpointListener(myBreakpointListener); + } + if (myDependentBreakpointListener != null) { + breakpointManager.getDependentBreakpointManager().removeListener(myDependentBreakpointListener); + } + } + if (myValueMarkers != null) { + myValueMarkers.clear(); + } + if (XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings().isUnmuteOnStop()) { + mySessionData.setBreakpointsMuted(false); + } + myDebuggerManager.removeSession(XDebugSessionImpl.this); + myDispatcher.getMulticaster().sessionStopped(); + myProject.putUserData(XDebuggerEditorLinePainter.CACHE, null); } - if (myDependentBreakpointListener != null) { - breakpointManager.getDependentBreakpointManager().removeListener(myDependentBreakpointListener); - } - } - if (myValueMarkers != null) { - myValueMarkers.clear(); - } - if (XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings().isUnmuteOnStop()) { - mySessionData.setBreakpointsMuted(false); - } - myStopped = true; - myDebuggerManager.removeSession(this); - myDispatcher.getMulticaster().sessionStopped(); - myProject.putUserData(XDebuggerEditorLinePainter.CACHE, null); + }); } public boolean isInactiveSlaveBreakpoint(final XBreakpoint breakpoint) { From 939c490895811da42cc6d6078f01239213f49b79 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 15:55:21 +0100 Subject: [PATCH 097/231] cast conversion: substitute type parameter bounds for recursive types (IDEA-136527) --- .../src/com/intellij/psi/util/TypeConversionUtil.java | 1 + .../CastConversionToTypeParameter.java | 7 +++++++ .../codeInsight/daemon/GenericsHighlightingTest.java | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 3213970cc260..1106633efdb0 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -403,6 +403,7 @@ public class TypeConversionUtil { final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1); if (class1 instanceof PsiTypeParameter) { for (PsiType type : class1.getExtendsListTypes()) { + type = substitutor1.substitute(type); if (TypesDistinctProver.provablyDistinct(type, typeArg2) && !isAssignable(type, typeArg2)) return false; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java new file mode 100644 index 000000000000..2499d4df03ef --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CastConversionToTypeParameter.java @@ -0,0 +1,7 @@ +import java.util.List; + +abstract class Test implements List { + private > T foo() { + return (T)this; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index ac8bb477b027..30b6cdd02f13 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -455,6 +455,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testCastConversionToTypeParameter() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass); From 66e83ed9aeae48411fa16d082ed2fe968a57632f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 16:27:34 +0100 Subject: [PATCH 098/231] do not get through class/lambda during detection of container sync (IDEA-136805) --- .../SleepWhileHoldingLockInspection.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java index a6d67a938aaa..ee8a136d8ed6 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/SleepWhileHoldingLockInspection.java @@ -45,9 +45,7 @@ public class SleepWhileHoldingLockInspection extends BaseInspection { return new SleepWhileHoldingLockVisitor(); } - private static class SleepWhileHoldingLockVisitor - extends BaseInspectionVisitor { - + private static class SleepWhileHoldingLockVisitor extends BaseInspectionVisitor { @Override public void visitMethodCallExpression( @NotNull PsiMethodCallExpression expression) { @@ -59,16 +57,14 @@ public class SleepWhileHoldingLockInspection extends BaseInspection { if (!"sleep".equals(methodName)) { return; } - final PsiMethod containingMethod = - PsiTreeUtil.getParentOfType(expression, PsiMethod.class); + final PsiMethod containingMethod = + PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class); boolean isSynced = false; - if (containingMethod != null && containingMethod - .hasModifierProperty(PsiModifier.SYNCHRONIZED)) { + if (containingMethod != null && containingMethod.hasModifierProperty(PsiModifier.SYNCHRONIZED)) { isSynced = true; } - final PsiSynchronizedStatement containingSyncStatement = - PsiTreeUtil.getParentOfType(expression, - PsiSynchronizedStatement.class); + final PsiSynchronizedStatement containingSyncStatement = + PsiTreeUtil.getParentOfType(expression, PsiSynchronizedStatement.class, true, PsiClass.class, PsiLambdaExpression.class); if (containingSyncStatement != null) { isSynced = true; } @@ -81,8 +77,7 @@ public class SleepWhileHoldingLockInspection extends BaseInspection { } final PsiClass methodClass = method.getContainingClass(); if (methodClass == null || - !InheritanceUtil.isInheritor(methodClass, - "java.lang.Thread")) { + !InheritanceUtil.isInheritor(methodClass, "java.lang.Thread")) { return; } registerMethodCallError(expression); From a7efd33b2b50142655304a3b86bfecd5806210b9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 16:41:49 +0100 Subject: [PATCH 099/231] cast conversion applicable for wildcard vs type parameter if bounds agree (IDEA-75628) --- .../intellij/psi/util/TypesDistinctProver.java | 8 +++++++- ...tinctProverForWildcardAndTypeParameter.java | 18 ++++++++++++++++++ .../daemon/GenericsHighlightingTest.java | 4 ++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java index 9a3fc135e16f..7d59b98b1fcf 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypesDistinctProver.java @@ -262,7 +262,13 @@ public class TypesDistinctProver { final PsiType boundBound = ((PsiWildcardType)bound).getBound(); if (boundBound != null && !boundBound.equals(type)) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(boundBound); - return psiClass == null || !(((PsiWildcardType)bound).isExtends() && possibleClasses.contains(psiClass)); + if (psiClass == null) { + return true; + } + if (psiClass instanceof PsiTypeParameter) { + return try2ProveTypeParameterDistinct(type, psiClass); + } + return !(((PsiWildcardType)bound).isExtends() && possibleClasses.contains(psiClass)); } return false; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java new file mode 100644 index 000000000000..183eed87cf16 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeDistinctProverForWildcardAndTypeParameter.java @@ -0,0 +1,18 @@ +abstract class Test { + interface Selection {} + interface CriteriaQuery { + void select(Selection selection); + } + + private void foo(CriteriaQuery criteria, Selection array) { + criteria.select((Selection)array); + } + + private void foo1(CriteriaQuery criteria, Selection array) { + criteria.select((Selection)array); + } + + private void foo2(CriteriaQuery criteria, Selection array) { + criteria.select((Selection)array); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 30b6cdd02f13..d61c5f0f096d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -459,6 +459,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testTypeDistinctProverForWildcardAndTypeParameter() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass); From a3dbdd52f3bacec1a7cd91003b1198d05d9cb081 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Fri, 20 Feb 2015 22:02:45 +0300 Subject: [PATCH 100/231] OC-11626 Debugger cannot inspect Swift object variables compiled with Xcode 6.3 (6D520o) Replaced Xcode setting with registry option. Refactored SwiftDebug test --- platform/util/resources/misc/registry.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index c4f1f70276e6..c324e0870738 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -540,3 +540,5 @@ git.status.write=true cidr.cygwin.cmakePermissionsFix=true cidr.cygwin.cmakePermissionsFix.description=Update permissions for the bin/ folder inside the installed IDE so that the bundled CMake could run +cidr.lldb.enableXcodeLLDB=false +cidr.lldb.enableXcodeLLDB.description=Enable LLDB from Xcode From 0d5947acd8fc0b627978c83cbc497334bbc48676 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 20:14:55 +0100 Subject: [PATCH 101/231] add file header to test class templates (IDEA-136582) --- .../fileTemplates/code/Groovy JUnit Test Case.groovy.ft | 1 + plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft | 1 + plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft | 1 + plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft | 1 + 4 files changed, 4 insertions(+) diff --git a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.ft b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.ft index 893f71508fb2..730f0b4ca4cb 100644 --- a/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.ft +++ b/plugins/groovy/groovy-psi/resources/fileTemplates/code/Groovy JUnit Test Case.groovy.ft @@ -1,4 +1,5 @@ import groovy.util.GroovyTestCase +#parse("File Header.java") public class ${NAME} { ${BODY} } \ No newline at end of file diff --git a/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft b/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft index 6d2a3b3c12af..72577b0ea7d8 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft +++ b/plugins/junit/src/fileTemplates/code/JUnit3 Test Class.java.ft @@ -1,4 +1,5 @@ import junit.framework.TestCase; +#parse("File Header.java") public class ${NAME} extends TestCase { ${BODY} } \ No newline at end of file diff --git a/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft b/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft index 5d58064d098f..cc1f599bfbb6 100644 --- a/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft +++ b/plugins/junit/src/fileTemplates/code/JUnit4 Test Class.java.ft @@ -1,4 +1,5 @@ import static org.junit.Assert.*; +#parse("File Header.java") public class ${NAME} { ${BODY} } \ No newline at end of file diff --git a/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft b/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft index 1ebebc04a62c..b60235c8f1f1 100644 --- a/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft +++ b/plugins/testng/src/fileTemplates/code/TestNG Test Class.java.ft @@ -1,4 +1,5 @@ import static org.testng.Assert.*; +#parse("File Header.java") public class ${NAME} { ${BODY} } \ No newline at end of file From ff5ce8e6bc4a76b6e6f128d431a6a2d74111db31 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 20:33:54 +0100 Subject: [PATCH 102/231] hide block from inspection's html presentation (IDEA-136363) --- .../src/com/intellij/codeInspection/ex/DescriptorComposer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java index c2fef7068dea..2ff2a881b903 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java @@ -182,6 +182,8 @@ public class DescriptorComposer extends HTMLComposerImpl { descriptionTemplate = XmlStringUtil.stripHtml(descriptionTemplate); } else { + descriptionTemplate = StringUtil.replace(descriptionTemplate, "", "'"); + descriptionTemplate = StringUtil.replace(descriptionTemplate, "", "'"); descriptionTemplate = XmlStringUtil.escapeString(descriptionTemplate); } //noinspection HardCodedStringLiteral From e4e12a068ac74b037f0f2c000b0709680ab6561b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 21:23:20 +0100 Subject: [PATCH 103/231] icon in inspection's settings fixed (IDEA-135474) --- .../com/intellij/codeHighlighting/HighlightDisplayLevel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java index 738e970fbca1..2de6b80ee9f4 100644 --- a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java +++ b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java @@ -60,7 +60,7 @@ public class HighlightDisplayLevel { */ @Deprecated public static final HighlightDisplayLevel INFO = new HighlightDisplayLevel(HighlightSeverity.INFO, DO_NOT_SHOW.getIcon()); - public static final HighlightDisplayLevel WEAK_WARNING = new HighlightDisplayLevel(HighlightSeverity.WEAK_WARNING, DO_NOT_SHOW.getIcon()); + public static final HighlightDisplayLevel WEAK_WARNING = new HighlightDisplayLevel(HighlightSeverity.WEAK_WARNING, createIconByKey(CodeInsightColors.WEAK_WARNING_ATTRIBUTES)); public static final HighlightDisplayLevel NON_SWITCHABLE_ERROR = new HighlightDisplayLevel(HighlightSeverity.ERROR); From 9fc640a8f07f1fcd62533d4550ccd14b00e748c1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 21:34:04 +0100 Subject: [PATCH 104/231] ensure correct expression is checked during read before write variable check (IDEA-135937) --- .../psi/controlFlow/ControlFlowUtil.java | 1 + .../FieldInitializedUsedInLambda.java | 17 +++++++++++++++++ .../daemon/lambda/LambdaHighlightingTest.java | 1 + 3 files changed, 19 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java index cc632cae8983..64169e127a6c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java @@ -852,6 +852,7 @@ public class ControlFlowUtil { private static PsiReferenceExpression findReferenceTo(PsiElement element, PsiVariable variable) { if (element instanceof PsiReferenceExpression + && !((PsiReferenceExpression)element).isQualified() && ((PsiReferenceExpression)element).resolve() == variable) { return (PsiReferenceExpression)element; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java new file mode 100644 index 000000000000..409670629123 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FieldInitializedUsedInLambda.java @@ -0,0 +1,17 @@ + +import java.util.Comparator; + +class Test { + private final int x; + + public Test(int x) { + this.x = x; + } + + public static final Comparator comparator = (o1, o2) -> { + if (o1.x == o2.x) { + } + this.x != o2.x; + return 0; + }; +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 868982e18bb8..673a5cfaa44a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -32,6 +32,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testStaticAccess() { doTest(); } public void testEffectiveFinal() { doTest(); } + public void testFieldInitializedUsedInLambda() {doTest();} public void testReassignUsedVars() { doTest(); } public void testLambdaContext() { doTest(); } public void testReturnTypeCompatibility() { doTest(); } From 81ed04a7dc1dfd43f64e3e9a98a596071db0654f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 22:03:19 +0100 Subject: [PATCH 105/231] search for method implementations with correct substitutor --- .../impl/ImplementAbstractMethodHandler.java | 6 +++++- ...erMultipleImplementationsAlreadyExist.java | 20 +++++++++++++++++++ ...reMultipleImplementationsAlreadyExist.java | 15 ++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java index c8b7da8aed28..e62fa10e4550 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java @@ -40,7 +40,9 @@ import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.ui.components.JBList; import com.intellij.util.IncorrectOperationException; @@ -180,7 +182,9 @@ public class ImplementAbstractMethodHandler { ArrayList list = new ArrayList(); for (PsiClass inheritor : ClassInheritorsSearch.search(psiClass, true)) { if (!inheritor.isInterface()) { - PsiMethod method = inheritor.findMethodBySignature(myMethod, true); + final PsiSubstitutor classSubstitutor = TypeConversionUtil.getClassSubstitutor(psiClass, inheritor, PsiSubstitutor.EMPTY); + LOG.assertTrue(classSubstitutor != null); + PsiMethod method = MethodSignatureUtil.findMethodBySignature(inheritor, myMethod.getSignature(classSubstitutor), true); if (method == null || !method.getContainingClass().equals(psiClass)) continue; list.add(inheritor); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java new file mode 100644 index 000000000000..c83805dbb2f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/afterMultipleImplementationsAlreadyExist.java @@ -0,0 +1,20 @@ +// "Implement method 'foo'" "true" + +abstract class A { + abstract String foo(T t); +} + +class B extends A { + + @Override + String foo(String s1) { + return null; + } +} + +class ABC extends A { + @Override + String foo(Integer integer) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java new file mode 100644 index 000000000000..eb475259b1e9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementMethods/beforeMultipleImplementationsAlreadyExist.java @@ -0,0 +1,15 @@ +// "Implement method 'foo'" "true" + +abstract class A { + abstract String foo(T t); +} + +class B extends A { + + @Override + String foo(String s1) { + return null; + } +} + +class ABC extends A {} \ No newline at end of file From 0c76e675eccf722720d1fe4c3147add1f233827b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Feb 2015 22:12:23 +0100 Subject: [PATCH 106/231] testdata for IDEA-134277 --- .../lambda/graphInference/IDEA134277.java | 18 ++++++++++++++++++ .../lambda/GraphInferenceHighlightingTest.java | 4 ++++ 2 files changed, 22 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java new file mode 100644 index 000000000000..e0956a029943 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA134277.java @@ -0,0 +1,18 @@ +import java.util.concurrent.Future; + +class TypeInferenceBug +{ + public interface Callback { + void done(V value); + } + + public static void addCallback(Future future, Callback callback) {} + + public static Callback createCallback() { + return value -> {}; + } + + public static void bind(Future future) { + addCallback(future, createCallback()); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index 4d04b70256b1..8e777ddaf0a7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -263,6 +263,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase doTest(); } + public void testIDEA134277() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); } From 5af5e21caf705294f7cb05a648ffa79bb1f53f6b Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Sat, 21 Feb 2015 00:05:59 +0300 Subject: [PATCH 107/231] History: share entries, use own cursors. --- .../console/ConsoleExecuteAction.java | 16 +---- .../console/ConsoleHistoryController.java | 62 ++++++++++++++----- .../console}/ConsoleHistoryModel.java | 19 ++++-- .../execution/console/DuplexConsoleView.java | 11 ++-- .../console/LanguageConsoleBuilder.java | 28 +++------ .../AbstractConsoleRunnerWithHistory.java | 8 +-- .../groovy/console/GroovyShellActionBase.java | 2 +- .../python/console/PydevConsoleRunner.java | 23 +++---- 8 files changed, 86 insertions(+), 83 deletions(-) rename platform/{platform-impl/src/com/intellij/execution/process => lang-impl/src/com/intellij/execution/console}/ConsoleHistoryModel.java (82%) diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java index 1aa103dfa6b1..f1cf7487bde4 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java @@ -17,7 +17,6 @@ package com.intellij.execution.console; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupManager; -import com.intellij.execution.process.ConsoleHistoryModel; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -108,7 +107,6 @@ public class ConsoleExecuteAction extends DumbAwareAction { } public static abstract class ConsoleExecuteActionHandler { - private ConsoleHistoryModel myCommandHistoryModel; private boolean myAddToHistory = true; final boolean myPreserveMarkup; @@ -119,18 +117,6 @@ public class ConsoleExecuteAction extends DumbAwareAction { myPreserveMarkup = preserveMarkup; } - @NotNull - public ConsoleHistoryModel getConsoleHistoryModel() { - if (myCommandHistoryModel == null) { - myCommandHistoryModel = new ConsoleHistoryModel(); - } - return myCommandHistoryModel; - } - - void setConsoleHistoryModel(@NotNull ConsoleHistoryModel model) { - myCommandHistoryModel = model; - } - public boolean isEmptyCommandExecutionAllowed() { return true; } @@ -162,7 +148,7 @@ public class ConsoleExecuteAction extends DumbAwareAction { } private void addToCommandHistoryAndExecute(@NotNull LanguageConsoleView consoleView, @NotNull String text) { - getConsoleHistoryModel().addToHistory(text); + ConsoleHistoryController.addToHistory(consoleView, text); doExecute(text, consoleView); } diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java index e4bdbdca11a2..155158367d7e 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java @@ -16,7 +16,6 @@ package com.intellij.execution.console; import com.intellij.codeInsight.lookup.LookupManager; -import com.intellij.execution.process.ConsoleHistoryModel; import com.intellij.ide.scratch.ScratchFileService; import com.intellij.lang.Language; import com.intellij.openapi.Disposable; @@ -40,6 +39,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringHash; import com.intellij.openapi.util.text.StringUtil; @@ -75,8 +75,11 @@ import java.util.*; */ public class ConsoleHistoryController { + private static final Key CONTROLLER_KEY = Key.create("CONTROLLER_KEY"); + private static final Logger LOG = Logger.getInstance("com.intellij.execution.console.ConsoleHistoryController"); + /** @noinspection MismatchedQueryAndUpdateOfCollection*/ private final static FactoryMap ourModels = new FactoryMap() { @Override protected Map createMap() { @@ -86,7 +89,7 @@ public class ConsoleHistoryController { @Nullable @Override protected ConsoleHistoryModel create(String key) { - return new ConsoleHistoryModel(); + return new ConsoleHistoryModel(null); } }; @@ -99,9 +102,8 @@ public class ConsoleHistoryController { private long myLastSaveStamp; @Deprecated - public ConsoleHistoryController(@NotNull String type, @Nullable String persistenceId, - @NotNull LanguageConsoleView console, @NotNull ConsoleHistoryModel model) { - this(new ConsoleRootType(type, null) { }, persistenceId, console, model); + public ConsoleHistoryController(@NotNull String type, @Nullable String persistenceId, @NotNull LanguageConsoleView console) { + this(new ConsoleRootType(type, null) { }, persistenceId, console); } public ConsoleHistoryController(@NotNull ConsoleRootType rootType, @Nullable String persistenceId, @NotNull LanguageConsoleView console) { @@ -110,8 +112,28 @@ public class ConsoleHistoryController { private ConsoleHistoryController(@NotNull ConsoleRootType rootType, @Nullable String persistenceId, @NotNull LanguageConsoleView console, @NotNull ConsoleHistoryModel model) { - myHelper = new ModelHelper(rootType, fixNullPersistenceId(persistenceId, console), model); + myHelper = new ModelHelper(rootType, fixNullPersistenceId(persistenceId, console), model.copy()); myConsole = console; + console.getVirtualFile().putUserData(CONTROLLER_KEY, this); + } + + public static ConsoleHistoryController getController(LanguageConsoleView console) { + return console.getVirtualFile().getUserData(CONTROLLER_KEY); + } + + public static void addToHistory(@NotNull LanguageConsoleView consoleView, @Nullable String command) { + ConsoleHistoryController controller = getController(consoleView); + if (controller != null) { + controller.addToHistory(command); + } + } + + public void addToHistory(@Nullable String command) { + getModel().addToHistory(command); + } + + public boolean hasHistory() { + return getModel().getHistory().isEmpty(); } private static String fixNullPersistenceId(@Nullable String persistenceId, @NotNull LanguageConsoleView console) { @@ -127,26 +149,29 @@ public class ConsoleHistoryController { return this; } - public ConsoleHistoryModel getModel() { + ConsoleHistoryModel getModel() { return myHelper.getModel(); } public void install() { + FileDocumentManager.getInstance().saveAllDocuments(); if (myHelper.getId() != null) { ApplicationManager.getApplication().getMessageBus().connect(myConsole).subscribe( ProjectEx.ProjectSaved.TOPIC, new ProjectEx.ProjectSaved() { - @Override - public void saved(@NotNull final Project project) { - saveHistory(); - } - }); + @Override + public void saved(@NotNull final Project project) { + saveHistory(); + } + }); Disposer.register(myConsole, new Disposable() { @Override public void dispose() { saveHistory(); } }); - loadHistory(myHelper.getId()); + if (myHelper.getModel().getHistorySize() == 0) { + loadHistory(myHelper.getId()); + } } configureActions(); myLastSaveStamp = getCurrentTimeStamp(); @@ -483,14 +508,15 @@ public class ConsoleHistoryController { OutputStream os = null; try { - final XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer(); + os = new SafeFileOutputStream(file); + XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer(); try { serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " "); } catch (Exception ignored) { // not recognized } - serializer.setOutput(os = new SafeFileOutputStream(file), CharsetToolkit.UTF8); + serializer.setOutput(os, CharsetToolkit.UTF8); saveHistory(serializer); serializer.flush(); } @@ -499,7 +525,9 @@ public class ConsoleHistoryController { } finally { try { - os.close(); + if (os != null) { + os.close(); + } } catch (Exception ignored) { // nothing @@ -517,7 +545,7 @@ public class ConsoleHistoryController { AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { VirtualFile file = HistoryRootType.getInstance().findFile(null, getHistoryName(myRootType, myId), ScratchFileService.Option.create_if_missing); - VfsUtil.saveText(file, StringUtil.join(ContainerUtil.reverse(getModel().getHistory()), myRootType.getEntrySeparator())); + VfsUtil.saveText(file, StringUtil.join(getModel().getHistory(), myRootType.getEntrySeparator())); } finally { token.finish(); diff --git a/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryModel.java similarity index 82% rename from platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java rename to platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryModel.java index 0e597c5089ce..415d0acd47e0 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ConsoleHistoryModel.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryModel.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.execution.process; +package com.intellij.execution.console; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.util.SimpleModificationTracker; @@ -27,11 +27,22 @@ import java.util.List; /** * @author Gregory.Shrago */ -public class ConsoleHistoryModel extends SimpleModificationTracker { +class ConsoleHistoryModel extends SimpleModificationTracker { + /** @noinspection FieldCanBeLocal*/ + private final ConsoleHistoryModel myMasterModel; // hard ref private int myHistoryCursor = -1; - private final LinkedList myHistory = new LinkedList(); + private final LinkedList myHistory; - public void addToHistory(String statement) { + ConsoleHistoryModel(ConsoleHistoryModel masterModel) { + myMasterModel = masterModel; + myHistory = myMasterModel == null ? new LinkedList() : myMasterModel.myHistory; + } + + ConsoleHistoryModel copy() { + return new ConsoleHistoryModel(this); + } + + public void addToHistory(@Nullable String statement) { if (StringUtil.isEmptyOrSpaces(statement)) return; int maxHistorySize = getMaxHistorySize(); diff --git a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java index 3c7ab3eedeff..68a4f836d0fb 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java +++ b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.Disposer; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -199,14 +200,14 @@ public class DuplexConsoleView ext List actions = Lists.newArrayList(); actions.addAll(Arrays.asList(myPrimaryConsoleView.createConsoleActions())); actions.add(mySwitchConsoleAction); - addExtraActions(actions); + + LanguageConsoleView langConsole = ContainerUtil.findInstance(Arrays.asList(myPrimaryConsoleView, mySecondaryConsoleView), LanguageConsoleView.class); + ConsoleHistoryController controller = langConsole != null ? ConsoleHistoryController.getController(langConsole) : null; + if (controller != null) actions.add(controller.getBrowseHistory()); return ArrayUtil.toObjectArray(actions, AnAction.class); } - protected void addExtraActions(List actions) { - } - @Override public void allowHeavyFilters() { myPrimaryConsoleView.allowHeavyFilters(); @@ -267,7 +268,7 @@ public class DuplexConsoleView ext } @Override - public void update(final AnActionEvent event) { + public void update(@NotNull AnActionEvent event) { super.update(event); final Presentation presentation = event.getPresentation(); final boolean isRunning = myProcessHandler != null && !myProcessHandler.isProcessTerminated(); diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java index e55acb4148be..fca776ec2e66 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java @@ -27,7 +27,6 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -110,17 +109,17 @@ public final class LanguageConsoleBuilder { private void doInitAction(@NotNull LanguageConsoleView console, @NotNull BaseConsoleExecuteActionHandler executeActionHandler, @NotNull String historyType) { ConsoleExecuteAction action = new ConsoleExecuteAction(console, executeActionHandler, executionEnabled); action.registerCustomShortcutSet(action.getShortcutSet(), console.getConsoleEditor().getComponent()); - setupHistoryController(console, historyType, null, executeActionHandler); + new ConsoleHistoryController(historyType, null, console).install(); } /** * todo This API doesn't look good, but it is much better than force client to know low-level details */ - public static Pair registerExecuteAction(@NotNull LanguageConsoleView console, - @NotNull final Consumer executeActionHandler, - @NotNull String historyType, - @Nullable String historyPersistenceId, - @Nullable Condition enabledCondition) { + public static AnAction registerExecuteAction(@NotNull LanguageConsoleView console, + @NotNull final Consumer executeActionHandler, + @NotNull String historyType, + @Nullable String historyPersistenceId, + @Nullable Condition enabledCondition) { ConsoleExecuteAction.ConsoleExecuteActionHandler handler = new ConsoleExecuteAction.ConsoleExecuteActionHandler(true) { @Override void doExecute(@NotNull String text, @NotNull LanguageConsoleView consoleView) { @@ -130,19 +129,8 @@ public final class LanguageConsoleBuilder { ConsoleExecuteAction action = new ConsoleExecuteAction(console, handler, enabledCondition); action.registerCustomShortcutSet(action.getShortcutSet(), console.getConsoleEditor().getComponent()); - - return new Pair(action, setupHistoryController(console, historyType, historyPersistenceId, handler)); - } - - @NotNull - private static ConsoleHistoryController setupHistoryController(@NotNull LanguageConsoleView console, - @NotNull String historyType, - @Nullable String historyPersistenceId, - @NotNull ConsoleExecuteAction.ConsoleExecuteActionHandler handler) { - ConsoleHistoryController historyController = new ConsoleHistoryController(new ConsoleRootType(historyType, null) {}, historyPersistenceId, console); - historyController.install(); - handler.setConsoleHistoryModel(historyController.getModel()); - return historyController; + new ConsoleHistoryController(historyType, historyPersistenceId, console).install(); + return action; } public LanguageConsoleBuilder gutterContentProvider(@Nullable GutterContentProvider value) { diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java index 8bbbe7cfbe95..e9009e3300fa 100644 --- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java +++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java @@ -131,7 +131,7 @@ public abstract class AbstractConsoleRunnerWithHistory() { @Override public JComponent compute() { - return getLanguageConsole().getConsoleEditor().getContentComponent(); + return getConsoleView().getConsoleEditor().getContentComponent(); } }); contentDescriptor.setAutoFocusContent(isAutoFocusContent()); @@ -139,7 +139,7 @@ public abstract class AbstractConsoleRunnerWithHistory actions = fillToolBarActions(toolbarActions, defaultExecutor, contentDescriptor); - registerActionShortcuts(actions, getLanguageConsole().getConsoleEditor().getComponent()); + registerActionShortcuts(actions, getConsoleView().getConsoleEditor().getComponent()); registerActionShortcuts(actions, panel); showConsole(defaultExecutor, contentDescriptor); @@ -234,10 +234,6 @@ public abstract class AbstractConsoleRunnerWithHistory myEnvironmentVariables; private String myCommandLine; private String[] myStatementsToExecute = ArrayUtil.EMPTY_STRING_ARRAY; - private ConsoleHistoryController myHistoryController; public static Key CONSOLE_KEY = new Key("PYDEV_CONSOLE_KEY"); @@ -273,7 +272,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory= myConsoleExecuteActionHandler.getPythonIndent() && - isIndentSubstring(getLanguageConsole().getEditorDocument().getText())); + isIndentSubstring(getConsoleView().getEditorDocument().getText())); } }; upAction.registerCustomShortcutSet(KeyEvent.VK_BACK_SPACE, 0, null); @@ -812,9 +811,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory Date: Sat, 21 Feb 2015 01:53:07 +0300 Subject: [PATCH 108/231] PY-14977 PyCharm is not obeying my file specific code style for HTML BaseLanguage is HTML, not Django now --- .../python/templateLanguages/PythonTemplateLanguage.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java b/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java index 28a7e082ec65..b5ccf9bd6eb7 100644 --- a/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java +++ b/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateLanguage.java @@ -20,10 +20,6 @@ public abstract class PythonTemplateLanguage extends Language implements Templat super(baseLanguage, ID, mimeTypes); } - protected PythonTemplateLanguage(@NotNull @NonNls final String id) { - super(id); - } - /** * @return template language readable name */ From 0f2577f77d324cbbc460ea73521b6bc7c69751d5 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Sat, 21 Feb 2015 11:00:54 +0300 Subject: [PATCH 109/231] IDEA-136452 Can't surround with {} code starting from the comment under if statement second attempt. first one didn't account for cases when end-of-line comment is a statement's child node --- .../java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java index 65c6777bcbbb..e4103ce1a9c9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/CodeInsightUtil.java @@ -106,7 +106,7 @@ public class CodeInsightUtil { if (parent == null) return PsiElement.EMPTY_ARRAY; while (true) { if (parent instanceof PsiStatement) { - if (!(element1 instanceof PsiComment || element2 instanceof PsiComment)) { + if (!(element1 instanceof PsiComment)) { parent = parent.getParent(); } break; From d1caaab17bdb545fa4a7e1bd88484c9df85a56ba Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Sat, 21 Feb 2015 16:38:03 +0300 Subject: [PATCH 110/231] i18n: added inspection to detect suspicious locale languages. Will help for people who has wrong resource bundle association --- plugins/java-i18n/src/META-INF/plugin.xml | 6 + .../SuspiciousLocalesLanguagesInspection.java | 239 ++++++++++++++++++ .../suspiciousLanguages/simple1/p.properties | 0 .../simple1/p_en.properties | 0 .../suspiciousLanguages/simple2/p.properties | 1 + .../simple2/p_asd.properties | 1 + .../withAdditionalLocales/p.properties | 0 .../withAdditionalLocales/p_asd.properties | 0 .../SuspiciousLanguagesInspectionTest.java | 60 +++++ .../messages/PropertiesBundle.properties | 6 + .../properties/ResourceBundleManager.java | 8 +- .../DissociateResourceBundleAction.java | 22 +- .../SuspiciousLocalesLanguages.html | 5 + 13 files changed, 337 insertions(+), 11 deletions(-) create mode 100644 plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java create mode 100644 plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties create mode 100644 plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties create mode 100644 plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties create mode 100644 plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties create mode 100644 plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties create mode 100644 plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties create mode 100644 plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java create mode 100644 resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index c3e2c5aab225..3f042db7095e 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -54,6 +54,12 @@ enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.capitalization.TitleCapitalizationInspection"/> + com.intellij.codeInspection.capitalization.AnnotateCapitalizationIntention diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java new file mode 100644 index 000000000000..b9ec80f1a5b5 --- /dev/null +++ b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java @@ -0,0 +1,239 @@ +/* + * Copyright 2000-2015 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.codeInspection; + +import com.intellij.codeInspection.ex.BaseLocalInspectionTool; +import com.intellij.lang.properties.PropertiesBundle; +import com.intellij.lang.properties.PropertiesImplUtil; +import com.intellij.lang.properties.ResourceBundle; +import com.intellij.lang.properties.ResourceBundleManager; +import com.intellij.lang.properties.customizeActions.DissociateResourceBundleAction; +import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.InputValidator; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.intellij.reference.SoftLazyValue; +import com.intellij.ui.AnActionButton; +import com.intellij.ui.AnActionButtonRunnable; +import com.intellij.ui.ToolbarDecorator; +import com.intellij.ui.components.JBList; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashSet; +import org.jdom.Element; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + +import javax.swing.*; +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * @author Dmitry Batkovich + */ +public class SuspiciousLocalesLanguagesInspection extends BaseLocalInspectionTool { + private static final String ADDITIONAL_LANGUAGES_ATTR_NAME = "additionalLanguages"; + private final static SoftLazyValue> JAVA_LOCALES = new SoftLazyValue>() { + @NotNull + @Override + protected Set compute() { + final Set result = new HashSet(); + for (Locale locale : Locale.getAvailableLocales()) { + result.add(locale.getLanguage()); + } + return result; + } + }; + + private final List myAdditionalLanguages = new ArrayList(); + + @Nls + @NotNull + @Override + public String getDisplayName() { + return "Suspicious resource bundle locale languages"; + } + + @TestOnly + public void setAdditionalLanguages(List additionalLanguages) { + myAdditionalLanguages.clear(); + myAdditionalLanguages.addAll(additionalLanguages); + } + + @Override + public void readSettings(@NotNull Element node) throws InvalidDataException { + final String rawLanguages = node.getAttributeValue(ADDITIONAL_LANGUAGES_ATTR_NAME); + if (rawLanguages != null) { + myAdditionalLanguages.clear(); + myAdditionalLanguages.addAll(StringUtil.split(rawLanguages, ",")); + } + } + + @Override + public void writeSettings(@NotNull Element node) throws WriteExternalException { + if (!myAdditionalLanguages.isEmpty()) { + final ArrayList uniqueLanguages = ContainerUtil.newArrayList(ContainerUtil.newHashSet(myAdditionalLanguages)); + Collections.sort(uniqueLanguages); + final String locales = StringUtil.join(uniqueLanguages, ","); + node.setAttribute(ADDITIONAL_LANGUAGES_ATTR_NAME, locales); + } + } + + @Nullable + @Override + public JComponent createOptionsPanel() { + return new MyOptions().getComponent(); + } + + @Nullable + @Override + public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); + if (propertiesFile == null) { + return null; + } + final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); + final List files = resourceBundle.getPropertiesFiles(); + if (files.isEmpty()) { + return null; + } + List bundleLocales = ContainerUtil.mapNotNull(files, new Function() { + @Override + public Locale fun(PropertiesFile propertiesFile) { + final Locale locale = propertiesFile.getLocale(); + return locale == ResourceBundleManager.DEFAULT_LOCALE ? null : locale; + } + }); + bundleLocales = ContainerUtil.filter(bundleLocales, new Condition() { + @Override + public boolean value(Locale locale) { + return !JAVA_LOCALES.getValue().contains(locale.getLanguage()) && !myAdditionalLanguages.contains(locale.getLanguage()); + } + }); + if (bundleLocales.isEmpty()) { + return null; + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor(file, + PropertiesBundle.message( + "resource.bundle.contains.locales.with.suspicious.locale.languages.desciptor"), + new DissociateResourceBundleQuickFix(resourceBundle), + ProblemHighlightType.WEAK_WARNING, + true); + return new ProblemDescriptor[] {descriptor}; + } + + private static class DissociateResourceBundleQuickFix implements LocalQuickFix { + private final ResourceBundle myResourceBundle; + + private DissociateResourceBundleQuickFix(ResourceBundle bundle) { + myResourceBundle = bundle; + } + + @Nls + @NotNull + @Override + public String getName() { + return getFamilyName(); + } + + @NotNull + @Override + public String getFamilyName() { + return PropertiesBundle.message("dissociate.resource.bundle.quick.fix.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + DissociateResourceBundleAction.dissociate(Collections.singleton(myResourceBundle), project); + } + } + + private class MyOptions { + private JBList myAdditionalLocalesList; + + public MyOptions() { + myAdditionalLocalesList = new JBList(new MyListModel()); + myAdditionalLocalesList.setCellRenderer(new DefaultListCellRenderer()); + } + + public JPanel getComponent() { + final JPanel panel = new JPanel(new BorderLayout()); + panel.add(new JLabel(PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.label")), BorderLayout.NORTH); + panel.add( + ToolbarDecorator.createDecorator(myAdditionalLocalesList) + .setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + Messages.showInputDialog(panel, PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.input.text"), + PropertiesBundle.message("dissociate.resource.bundle.quick.fix.options.input.title"), null, "", new InputValidator() { + @Override + public boolean checkInput(String inputString) { + return 1 < inputString.length() && inputString.length() < 9 && !myAdditionalLanguages.contains(inputString); + } + + @Override + public boolean canClose(String inputString) { + if (inputString != null) { + myAdditionalLanguages.add(inputString); + ((MyListModel)myAdditionalLocalesList.getModel()).fireContentsChanged(); + } + return true; + } + }); + } + }) + .setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + final int index = myAdditionalLocalesList.getSelectedIndex(); + if (index > -1 && index < myAdditionalLanguages.size()) { + myAdditionalLanguages.remove(index); + ((MyListModel)myAdditionalLocalesList.getModel()).fireContentsChanged(); + } + } + }) + .setPreferredSize(new Dimension(-1, 100)) + .disableUpDownActions() + .createPanel(), + BorderLayout.CENTER); + return panel; + } + + private class MyListModel extends AbstractListModel { + @Override + public int getSize() { + return myAdditionalLanguages.size(); + } + + @Override + public Object getElementAt(int index) { + return myAdditionalLanguages.get(index); + } + + public void fireContentsChanged() { + fireContentsChanged(myAdditionalLanguages, -1, -1); + } + } + } +} diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple1/p_en.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties new file mode 100644 index 000000000000..cb17b36e6685 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p.properties @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties new file mode 100644 index 000000000000..cb17b36e6685 --- /dev/null +++ b/plugins/java-i18n/testData/inspections/suspiciousLanguages/simple2/p_asd.properties @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties b/plugins/java-i18n/testData/inspections/suspiciousLanguages/withAdditionalLocales/p_asd.properties new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java new file mode 100644 index 000000000000..784b6e9ea737 --- /dev/null +++ b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2015 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.codeInspection; + +import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.containers.ContainerUtil; + +import java.io.File; + +/** + * @author Dmitry Batkovich + */ +public class SuspiciousLanguagesInspectionTest extends LightCodeInsightFixtureTestCase { + @Override + protected String getBasePath() { + return PluginPathManager.getPluginHomePathRelative("java-i18n") + "/testData/inspections/suspiciousLanguages"; + } + + public void testSimple1() { + doTest(); + } + + public void testSimple2() { + doTest(); + } + + public void testWithAdditionalLocales() { + doTest("asd"); + } + + private void doTest(final String... additionalLocales) { + final File tesDataDir = new File(getHomePath() + File.separator + getBasePath() + File.separator + getTestName(true)); + final File[] files = tesDataDir.listFiles(); + assertNotNull(files); + for (File file : files) { + final String path = file.getAbsolutePath(); + myFixture.configureByFile(path); + } + final SuspiciousLocalesLanguagesInspection inspection = new SuspiciousLocalesLanguagesInspection(); + if (additionalLocales.length != 0) { + inspection.setAdditionalLanguages(ContainerUtil.newArrayList(additionalLocales)); + } + myFixture.enableInspections(inspection); + myFixture.checkHighlighting(); + } +} diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties index aefabc574b38..1a58d5b832a4 100644 --- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties +++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties @@ -60,3 +60,9 @@ inline.property.confirmation=Inline property ''{0}'' with value ''{1}''? alpha.unsorted.properties.file.inspection.display.name=Properties File or Resource Bundle is Alphabetically Unsorted trailing.spaces.in.property.inspection.ignore.visible.spaces=Ignore visible whitespaces + +resource.bundle.contains.locales.with.suspicious.locale.languages.desciptor=Resource bundle contains locales with suspicious locale languages +dissociate.resource.bundle.quick.fix.name=Dissociate Resource Bundle +dissociate.resource.bundle.quick.fix.options.label=Additional language codes\: +dissociate.resource.bundle.quick.fix.options.input.text=Inter language code +dissociate.resource.bundle.quick.fix.options.input.title=Additional Locale Languages diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 5d8487d468a2..626961e8b9f2 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -47,7 +47,7 @@ import java.util.regex.Matcher; }) public class ResourceBundleManager implements PersistentStateComponent { private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); - private final static Locale DEFAULT_LOCALE = new Locale("", "", ""); + public final static Locale DEFAULT_LOCALE = new Locale("", "", ""); private ResourceBundleManagerState myState = new ResourceBundleManagerState(); @@ -172,7 +172,11 @@ public class ResourceBundleManager implements PersistentStateComponent resourceBundles = extractResourceBundles(e); assert resourceBundles.size() > 0; - final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); - for (ResourceBundle resourceBundle : resourceBundles) { - fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); - for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { - fileEditorManager.closeFile(propertiesFile.getVirtualFile()); - } - ResourceBundleManager.getInstance(e.getProject()).dissociateResourceBundle(resourceBundle); - } - ProjectView.getInstance(project).refresh(); + dissociate(resourceBundles, project); } @Override @@ -79,6 +71,18 @@ public class DissociateResourceBundleAction extends AnAction { } } + public static void dissociate(final Collection resourceBundles, final Project project) { + final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + for (ResourceBundle resourceBundle : resourceBundles) { + fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); + for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { + fileEditorManager.closeFile(propertiesFile.getVirtualFile()); + } + ResourceBundleManager.getInstance(project).dissociateResourceBundle(resourceBundle); + } + ProjectView.getInstance(project).refresh(); + } + @NotNull private static Collection extractResourceBundles(final AnActionEvent event) { final Set targetResourceBundles = new HashSet(); diff --git a/resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html b/resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html new file mode 100644 index 000000000000..8a6f5535c32a --- /dev/null +++ b/resources-en/src/inspectionDescriptions/SuspiciousLocalesLanguages.html @@ -0,0 +1,5 @@ + + +Inspection detects locales which contain languages not included supported by Java. + + \ No newline at end of file From 05f1324905522d0af9b2fc4c2d6a1c5061b60129 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sat, 21 Feb 2015 21:35:33 +0100 Subject: [PATCH 111/231] speeding up netty initialization for some systems --- .../impl/src/com/intellij/compiler/server/BuildManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 9ceffac57eb4..9648285288a1 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -93,6 +93,7 @@ import io.netty.handler.codec.protobuf.ProtobufDecoder; import io.netty.handler.codec.protobuf.ProtobufEncoder; import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder; import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; +import io.netty.util.internal.ThreadLocalRandom; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.ide.PooledThreadExecutor; @@ -999,6 +1000,9 @@ public class BuildManager implements ApplicationComponent{ cmdLine.addParameter("-Didea.case.sensitive.fs=" + isFSCaseSensitive); } + // this will make netty initialization faster on some systems + cmdLine.addParameter("-Dio.netty.initialSeedUniquifier=" + ThreadLocalRandom.getInitialSeedUniquifier()); + boolean isProfilingMode = false; final String additionalOptions = config.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS; if (!StringUtil.isEmpty(additionalOptions)) { From 032be763669931ebaf4717081fd5e2e984054cc4 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 21 Feb 2015 23:09:52 +0100 Subject: [PATCH 112/231] duplicate window shadows to avoid resizing on HiDPI --- platform/icons/src/ide/shadow/bottom-left@2x.png | Bin 0 -> 1510 bytes .../icons/src/ide/shadow/bottom-right@2x.png | Bin 0 -> 1525 bytes platform/icons/src/ide/shadow/bottom@2x.png | Bin 0 -> 313 bytes platform/icons/src/ide/shadow/left@2x.png | Bin 0 -> 233 bytes platform/icons/src/ide/shadow/right@2x.png | Bin 0 -> 245 bytes platform/icons/src/ide/shadow/top-left@2x.png | Bin 0 -> 1055 bytes platform/icons/src/ide/shadow/top-right@2x.png | Bin 0 -> 1169 bytes platform/icons/src/ide/shadow/top@2x.png | Bin 0 -> 175 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 platform/icons/src/ide/shadow/bottom-left@2x.png create mode 100644 platform/icons/src/ide/shadow/bottom-right@2x.png create mode 100644 platform/icons/src/ide/shadow/bottom@2x.png create mode 100644 platform/icons/src/ide/shadow/left@2x.png create mode 100644 platform/icons/src/ide/shadow/right@2x.png create mode 100644 platform/icons/src/ide/shadow/top-left@2x.png create mode 100644 platform/icons/src/ide/shadow/top-right@2x.png create mode 100644 platform/icons/src/ide/shadow/top@2x.png diff --git a/platform/icons/src/ide/shadow/bottom-left@2x.png b/platform/icons/src/ide/shadow/bottom-left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..10e5d1c9c5f60e1ed3d5fde61550594f0a8da45e GIT binary patch literal 1510 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT3?e@WZDU|y3=Z%KasB`QKTu>8P%#AVH@#{F z8dq2n ztEX>ZXk=_+YG!U>X=QC=YiIA^=;Z9;>gMj@>E-R?>*pU37!({58WtWA85JE98yBCD zn3SB7nwFlCnU$TBo0ng3_L!s-0|WC#PZ!6Kh}NZH;Yr%&0?v|m|LeW9l>KbjdS~jq zT+L1PTX?w>90F7vCoRzk+?1l3WBsMT;*a#czaQ8RPtds?)^fP7KOyB7&+W1+_pJ>K zT&HT>?)tCnH7!N^4bxASwmdWWt}L@nF(opZZ=3@&H$Gy{Utny0QcZ@>b@Ps zOJum}8JrD`%!@XtfBju;U~<&KBg`jHCjXFvhb(h>i;`14Q02KFKMii$w>2J<2`_S* zDc%0BhI<+Nxd~e4oS(1vC$4B*So|pL#lwIfyb@Z85sREoy}9|3&qv?);f4F{RPNULq4H5w^5 zJ5roGMK}Z*j?bRVo48BNWm3Tg7tcuv2dDlN+T3xp(J|5|IP`?-iD^%5=I_#+@FZ!o zWS{~oXV9!O3#wx}D;p-XOmkRZYnPZYrF&;|YSp4Zmf%GWPmOQS;`Y(=-{>^S#zsSk zb^F94PtvNJ^VXeW3-Q9# zLfy_Z={whS5+?|;Wy+p*^V~Z3^vwH{T9!D8v<8cuJF9j0@xMaFYxRMF&)--cRcMUT ze!L{L<EU zo6?rXT`Q&pHdq~eduC~VRm3XUq`KIUV9s+sipk7h=MA>%^zzYsqVwrkHad z(w7>sGQF9B=L|>^j6*tRN^M71P@)yUUqd?7hKt zp0_@HO=TZ0?6mA#e@e}z**tu=#r(DstFygj4KhvflEn>iKSPZ8g0H82;VEjijK7h> zx9~>xgMUBX^5{qGso6iHJHB@BnK!>aJiYX4=6pH(pCyxaUEIO*bn6c3h0XstE9)Pa zo~iwFU3hz84ddrmJFm~%SNFeL_`Ko&N1tDP>MYq_YL(x&zv{I9ls`}Yz1OQ<`da#| h{f>vdyZ7z=Y5(p){$3S~6@vd$@?2>^W82M7QF literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/bottom-right@2x.png b/platform/icons/src/ide/shadow/bottom-right@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..771dfef1db73f41b2ea7be0e40733473558d8f22 GIT binary patch literal 1525 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT3?e@WZDU|y3=Z%KasB`QKTu>8P%#AVH@#{F z8dq2n ztEX>ZXk=_+YG!U>X=QC=YiIA^=;Z9;>gMj@>E-R?>*pU37!({58WtWA85JE98yBCD zn3SB7nwFlCnU$TBo0ng3_L!s-0|WB|PZ!6Kh{JQIJ5GCS!Q*`J<(&L;M&IiN|LJ&K zoHDs;>Xzz>Avp&bJe*!#cz=EW>z(sn|E#H6yLFyU^-UcEhK_o>2Ej>7I5;(by)XQ) zJR@Vx4#qdXd4=feSg0 z8Xj2BU<%r>zexEjC(oo7MZ-tE>-=weC?G9jsI)4oV~60c8%fKz1b)wVeOp%i z-S=iNg{E*_JbwK`LiZ+}Z#`}9w5!B)d7HDA9*C^~v5OgVr0MuYY5 z%|G|=P1}>Q`oxYaQ=8a!{Hfd$cYK=v&7{XB?qxUYH@#TnVWz~w=YBP7fy&}3&!@!C zHIaJpQKni$VpmXTNl$p2yp!0Yu)LRynSa)$NZ!&gvL zRTU?bHm-VgBYNAdbIu{}B_qABJFK16p1M1Sv1#HW6`sdS9%g->(;%`rq9{1U@9BqU zD^EYZ`+94_Rf7}U`Z;CqpBnT}n!jjEqE7VgnAM*a|71Ag=W@{?GEZ;LnYN{ip4{y( z{jlZSyWK9aTQ^-;bth6Q^V=!`Mv-uZ&rHd#=?DET=az2cyYAa4v-p8>zKqATIeWNU zPR&15AZ{I}qb3uyPa!^IWzF4*aSugpkKX$KrQ+QlO}(G1vVI#%>|3?<``W{gUI?yt z7P#BC;LPJEOJq;q;aMlJw=CJ+)cRV%EV1p&cZ=+mJsVJNr9Az)$`s}AXTQ%g7Z;i< zbwW0BF8}kN&!o<(Y%W#KGCwyXJU{I3gj?s0UB2ttteQ7_&icIu>565RCOYSyJ}un0 zpzP7yyV3r{O#w>_e5sq~`WS{h5vBAz3lA#{wt2!eB4&6^Um?*AB#G+#XrvW zvU+c(q4}MkM|OT$_cUYw_5aC*br1XM&d)M8*z^Bf^%ePF&(5~q)7zI_Q8Ksg!4>1* z#%)XN7jD1)G2_GG-uT3OdJm7Q|9`Q#JN}*hzq*%u{;_XgAT+0T-<)Tla?8`z&t;uc GLK6T(2Qp3o literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/bottom@2x.png b/platform/icons/src/ide/shadow/bottom@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ad69deefa9b67e4226fa9f50c71ab7ecb5087476 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^j6iJ2!3-pIHX4fosonse5LX~Qc)+W6;~zlR=$8cf z1v9ebWo4(OB*te%gogzBdAYkd*uEal|5uGfMp1{=f-zVoxkB`8K!)F*$6`eUZtYC=|jXQDR#E}C_c$YLXF!YNt Uu|L{l_zV;Pp00i_>zopr0AS56tpET3 literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/left@2x.png b/platform/icons/src/ide/shadow/left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..78c558d74d75db1d5863832ed29a8a0275d9173d GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG>!3-pmlb?qHsk8u}5LX~g2T+hRf$rIH}O zU?xUp7FITP4lZt9egPp7aY<=81tm329epD+3tI;lcW=LCeGlb;ss%h<978x{lT-ej eKX9Z&o`FH7l2Q5mKAU)ugFRjST-G@yGywqWC>*^2 literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/right@2x.png b/platform/icons/src/ide/shadow/right@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2afef8fd36d2cdc3f2c6a4a15d6bd6b587eddba GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG>!3-pmlb?qHsk8u}5LX~g2T+hRf$rIH}O zU?x9zZwFfo7bATgO*Lf&Gigb25g`G7UT!W9b~aWPW;sTu%=}$I)iRzgjv*Yf$tfwn q&i|S|apGrnWeJYj1Q%9*NfE~4N>*iMN$oQr$9uZ^xvXAt@y-BP%Dbps1v*qN=8@p{b>cH9a++?`&VTvH@#Mx0e$gHM3+%oNsAo6|98@`Gv&2fRTk^X;S4ZshisC25 zn=7~%JO0}367`KGXGUa1bCXN5L5Js6j#o>6-q4gi(6wgqE`R5aCYdX0yYJuTZ(-HA z6Z%zamZ?-pcbCT>bcNwu|@UP<3TIm?=zIB)JJ|ETKm2AZ?Z^oGB zUlM9CedWLW-kswu6LtyAK0RkuX0bu~>bW|*XBAvq(P?Jg`g7^w<1XKHk~f^6ojA>J zc3|I3(lANz7hlfAT_Po`+qy)`E6wSQTEE|1hvoEhn;KE*~OVzskLe8|>_-~UeJ zwtlcwi{~g7R=ATK?CHCuZ^ro=!>~(H0WU30XPvQF{zgL6ttsv1m8PV%dz}Qfteb!N z%^JyVyv|$HN@d=EpDT0j{GE$k0#|j?PGorg%Fg~(+OcfqJ@;^ty8j>Ir9VuN)>w5` zAahQWh}_Qgt0M3F&-wM~(yTR3%hLPh4V1S<)?}BiPx4R+wf>V>ta8bpf6LA#{JHAt@y-BP%Dbps1v*qN=8@p{b>?rw0T4JWd zrRsV+(QjVTI-3d>C$$bM zOr77A|2$`2x4grSRc#K}+3QXxwKwyXs7?FAs$%fRf6`aRg4hX$pR%sJQL++9Uo`21 znoQKg#Tv|ugr5yF4oXsrT((#lD6PO z{m@klS4;}AFnZi-ee>xw&fEz>?j46p5+pR;C0G>=Hc0S=hPE#_d@#_1Z$ZmsuSJ&_ zJ6^geurM?D_W4`z653yb4I1uKa&8$;DZH>-&?Yie~lK2#2v=6LlRUo(H~g&lLg&xyL9(Ubf|s+RX;thRwP_5DEWULn?=;L7s?3tK(A^Sr>Bc6_xhvJ|Ct67O z?(MccY`gNt_RnQ;>%FgbH2D7dXEF6s{i_gLSvvV>P}&k9pV#S0 kj<4o#K9Od1$)ffj|J9X|8$WJu6#^A3p00i_>zopr0E6O)EC2ui literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/top@2x.png b/platform/icons/src/ide/shadow/top@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a893e2458eec64fb9112636e507b4549b1388d9b GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{H!3-p;FD#!7q|5?*LR^6~8DM)^MiEe(P)U$q zFe3{y6B|1R7dJ1zfRKo|q_iAI)ah$LSusx+#}E$L Date: Sat, 21 Feb 2015 23:10:09 +0100 Subject: [PATCH 113/231] duplicate popup shadows to avoid resizing on HiDPI --- .../icons/src/ide/shadow/popup/bottom-left@2x.png | Bin 0 -> 356 bytes .../src/ide/shadow/popup/bottom-right@2x.png | Bin 0 -> 347 bytes platform/icons/src/ide/shadow/popup/bottom@2x.png | Bin 0 -> 134 bytes platform/icons/src/ide/shadow/popup/left@2x.png | Bin 0 -> 122 bytes platform/icons/src/ide/shadow/popup/right@2x.png | Bin 0 -> 122 bytes .../icons/src/ide/shadow/popup/top-left@2x.png | Bin 0 -> 242 bytes .../icons/src/ide/shadow/popup/top-right@2x.png | Bin 0 -> 242 bytes platform/icons/src/ide/shadow/popup/top@2x.png | Bin 0 -> 110 bytes 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 platform/icons/src/ide/shadow/popup/bottom-left@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/bottom-right@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/bottom@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/left@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/right@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/top-left@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/top-right@2x.png create mode 100644 platform/icons/src/ide/shadow/popup/top@2x.png diff --git a/platform/icons/src/ide/shadow/popup/bottom-left@2x.png b/platform/icons/src/ide/shadow/popup/bottom-left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..17b7f4d2682eef698c2dbe8be2715bf402228c7b GIT binary patch literal 356 zcmV-q0h|7bP)74PVwAMk~)4a_KT7K^B$fwty&hiAOu1D^qX z9Xbe%FoSuuY2Wi6j&O-vRr-jhfEPTtz^wX@)wZp2OS80XyAyDui!}ZmZQBK1 zPDMAqqiS3F(>M%hYu$bVBUPFALRYb_o3E+rM!>cng>h~Bp|;Wl3s};AmNehBA-iryJ-c-TKYr^LnObK+*Rs=bK@*_=*xHqjO-h~4I{9vF42(y0000 zOHaZ;6o%naE=80Y43WY@L&7aA3|>$cLI?(2xY8H`ZX_W_|Nk%Wt9eVBrem~h+T_`t zew{gUrk3^pCodDZmbQ4}iX&MoVc>&|q$dqI-ZyY2x6(~@;9cqi)7!(GOl2q?sYe5y zKPsRU8thiwU~lA0J`Fyod6O4;B=AC-aw=s$_7nIXdNIzHnzcO3f?Lv;bE(P^y|pch zRZv|$%GV;c*DIW=QeHsEy6*skBd0}d&B&fm4D)g?%>g*uUW0rp75mKdRE-Ne2yKFenWiU-#lvz=U tASW&?$zbQ%Vz5m+dX?-1GQo*PpKtrNBkwS|Y4iX9002ovPDHLkV1j5^k);3t literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/popup/bottom@2x.png b/platform/icons/src/ide/shadow/popup/bottom@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb4fcb9fbb95e5d1c563a4fee4a4247edcea8b91 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrA!VDza|7cbMDY*cj5LY0L2W;2K&jLzwl?3?( zr>BOwnW{_E)O!VDxIsIL4Aq(lRJLR^6~CJ_E)O!VDxIsIL4Aq(lRJLR^6~CJG;%8@`6Y(n+D8%dO;uyjqo173*<_k0~hT&95N)yOr22WQ%mvv4FO#m(W6tDmQ literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/popup/top-left@2x.png b/platform/icons/src/ide/shadow/popup/top-left@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6ca6530854f7ebf49c0aaa7056e4693b03dd95 GIT binary patch literal 242 zcmVPwx&W*E>rlRmLP>)ydvMfG24)w>oSr)pG zLjl^O6=*h>P(dFISg0MXDw+Yq4MP~i6lO5z_ZMtJJqAXcQvu(hc)f}tIei&wg0Gt8 zwbroXd^DJ|+5i>|9XTHj7JQpjTfqS?DM8J)PhbNlxbwi^Pz)Njc?)NFqy}sLBYEEy sUMaznL21k$ZtzYGTBo8k<{1lq0Lu*rNn`vHp8x;=07*qoM6N<$g0c}@WB>pF literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/popup/top-right@2x.png b/platform/icons/src/ide/shadow/popup/top-right@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..567bd08fbc83ae7fcc17b681b334ebfe8069eb54 GIT binary patch literal 242 zcmV9U6a>(iG*)Xh;;Sks2uc^aaG`>36!HJR$+<8}&^Ars&`st(5~Y;VKU$vP*REh8 z0YjBV2A)3T(1Q$87D~KnzTXTA{--d35jYm=)`fKq;}yslHZi+Pc*!Z8*I73OrTP|D z9AC!naO7ZDIdFg-EMUm4HYRw6J*;8O+qO;P%7GgkVZ&YXm^~$UhZA=#_|~7>4F;cZ s;hu8_)0p53u2Ax6Tx{^c3;OH$2GwE*k^i4cxBvhE07*qoM6N<$f{52-7XSbN literal 0 HcmV?d00001 diff --git a/platform/icons/src/ide/shadow/popup/top@2x.png b/platform/icons/src/ide/shadow/popup/top@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..495941809e23f40ae2667513dafcd6079e30a478 GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr7#0(^jw(VUBq<8{+LR^6~9GJc|p9bWxlmz(& vGqLfBGq_j10`hr1T^vI=WRnvU3K<+3m}W3s)D?Il0Mg~@>gTe~DWM4fzlRiE literal 0 HcmV?d00001 From c3602f3000cf1abff37c6c7dac0ad6b669d54060 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 21 Feb 2015 23:10:50 +0100 Subject: [PATCH 114/231] resize non @2x images on HiDPI devices --- .../src/com/intellij/util/ImageLoader.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/ImageLoader.java b/platform/util/src/com/intellij/util/ImageLoader.java index 1fcc08ea333b..b8ac405c97f3 100644 --- a/platform/util/src/com/intellij/util/ImageLoader.java +++ b/platform/util/src/com/intellij/util/ImageLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -30,6 +30,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; @@ -63,7 +65,14 @@ public class ImageLoader implements Serializable { public static Image loadFromUrl(@NotNull URL url) { for (Pair each : getFileNames(url.toString())) { try { - return loadFromStream(URLUtil.openStream(new URL(each.first)), each.second); + Image image = loadFromStream(URLUtil.openStream(new URL(each.first)), each.second); + + //we can't check all 3rd party plugins and convince the authors to add @2x icons. + // isHiDPI() != isRetina() => we should scale images manually + if (image != null && JBUI.isHiDPI() && !each.first.contains("@2x")) { + image = upscale(image); + } + return image; } catch (IOException ignore) { } @@ -71,6 +80,19 @@ public class ImageLoader implements Serializable { return null; } + @NotNull + private static Image upscale(Image image) { + float scale = JBUI.scale(1f); + int width = (int)(scale * image.getWidth(null)); + int height = (int)(scale * image.getHeight(null)); + @SuppressWarnings("UndesirableClassUsage") + BufferedImage tmp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = tmp.createGraphics(); + g.drawImage(image, AffineTransform.getScaleInstance(scale, scale), null); + image = tmp; + return image; + } + @Nullable public static Image loadFromUrl(URL url, boolean dark, boolean retina) { for (Pair each : getFileNames(url.toString(), dark, retina || JBUI.isHiDPI())) { From d18c455ea92cff6a6b77f76b83c8a0ff239a7586 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 21 Feb 2015 23:11:24 +0100 Subject: [PATCH 115/231] +is & +has methods --- .../util/src/com/intellij/util/SystemProperties.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/SystemProperties.java b/platform/util/src/com/intellij/util/SystemProperties.java index 7929dd1ff629..14b6999cb868 100644 --- a/platform/util/src/com/intellij/util/SystemProperties.java +++ b/platform/util/src/com/intellij/util/SystemProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -135,4 +135,12 @@ public class SystemProperties { public static String getJavaVendor() { return System.getProperty("java.vendor"); } + + public static boolean is(String key) { + return getBooleanProperty(key, false); + } + + public static boolean has(String key) { + return System.getProperty(key) != null; + } } From fb80b1b9e8dc1429be0892c223792f38a8a41a68 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 21 Feb 2015 23:12:05 +0100 Subject: [PATCH 116/231] rewrite calculation of isHiDPI --- .../util/src/com/intellij/util/ui/JBUI.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 0c80b543d838..70f4539f958a 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -17,6 +17,7 @@ package com.intellij.util.ui; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.border.CustomLineBorder; +import com.intellij.util.SystemProperties; import javax.swing.*; import javax.swing.border.Border; @@ -26,7 +27,27 @@ import java.awt.*; * @author Konstantin Bulenkov */ public class JBUI { - private static boolean IS_HIDPI = !SystemInfo.isMac && ("true".equals(System.getProperty("hidpi")) || "true".equals(System.getProperty("is.hidpi"))); + private static boolean IS_HIDPI = calculateHiDPI(); + + private static boolean calculateHiDPI() { + if (SystemInfo.isMac) { + return false; + } + + if (SystemProperties.is("hidpi")) { + return true; + } + + if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { + return false; + } + + if (SystemInfo.isWindows && getSystemDPI() > 144) { + return true; + } + + return false; + } private static int getSystemDPI() { try { From ae11763e7f5a58ed537bb1daf587a92d21d8facd Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 21 Feb 2015 23:22:57 +0100 Subject: [PATCH 117/231] HiDPI fix Splash custom paintings --- platform/platform-impl/src/com/intellij/ui/Splash.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/Splash.java b/platform/platform-impl/src/com/intellij/ui/Splash.java index 0bee1412af15..fcab3aa223ab 100644 --- a/platform/platform-impl/src/com/intellij/ui/Splash.java +++ b/platform/platform-impl/src/com/intellij/ui/Splash.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -47,7 +47,7 @@ public class Splash extends JDialog implements StartupProgress { @Nullable public static Rectangle BOUNDS; private final Icon myImage; - private int myProgressHeight = 2; + private int myProgressHeight = JBUI.scale(2); private Color myProgressColor = null; private int myProgressY; private float myProgress; @@ -102,7 +102,7 @@ public class Splash extends JDialog implements StartupProgress { this(info.getSplashImageUrl(), info.getSplashTextColor()); if (info instanceof ApplicationInfoImpl) { final ApplicationInfoImpl appInfo = (ApplicationInfoImpl)info; - myProgressHeight = 2; + myProgressHeight = JBUI.scale(2); myProgressColor = appInfo.getProgressColor(); myProgressY = appInfo.getProgressY(); myProgressTail = appInfo.getProgressTailIcon(); @@ -143,8 +143,8 @@ public class Splash extends JDialog implements StartupProgress { g.setColor(color); g.fillRect(1, getProgressY(), width, getProgressHeight()); if (myProgressTail != null) { - myProgressTail.paintIcon(this, g, width - (myProgressTail.getIconWidth()/2), - getProgressY() - (myProgressTail.getIconHeight() - getProgressHeight())/2); + myProgressTail.paintIcon(this, g, width - (myProgressTail.getIconWidth() / JBUI.scale(1) / 2 * JBUI.scale(1)), + getProgressY() - (myProgressTail.getIconHeight() - getProgressHeight()) / JBUI.scale(1) / 2 * JBUI.scale(1)); //I'll buy you a beer if you understand this line without playing with it } myProgressLastPosition = progressWidth; } From 4e10661379bce1856211e061203948cb81691145 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sun, 22 Feb 2015 02:00:38 +0100 Subject: [PATCH 118/231] HiDPI: get system font sizes on Linux --- .../src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 156c39657609..390c0190c71d 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -56,7 +56,7 @@ public class DarculaLaf extends BasicLookAndFeel { public DarculaLaf() { try { - if (SystemInfo.isWindows || SystemInfo.isLinux) { + if (SystemInfo.isWindows) { base = new IdeaLaf(); } else { final String name = UIManager.getSystemLookAndFeelClassName(); From 5bcf4c7f67a4e426b2d4c097d18ccc131acb16f8 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Sun, 22 Feb 2015 14:30:44 +0300 Subject: [PATCH 119/231] Switch debugger reader's sleeping policy to BLOCKING (PY-15122) Because of changes in BaseOutputReader we can't call readAvailableBlocking if sleeping policy is not BLOCKING. --- .../com/jetbrains/python/debugger/pydev/RemoteDebugger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index cd2c6e2f0b4d..e39f45f1b3a9 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -488,7 +488,7 @@ public class RemoteDebugger implements ProcessDebugger { private StringBuilder myTextBuilder = new StringBuilder(); private DebuggerReader(final InputStream stream) throws IOException { - super(stream, CharsetToolkit.UTF8_CHARSET); //TODO: correct encoding? + super(stream, CharsetToolkit.UTF8_CHARSET, SleepingPolicy.BLOCKING); //TODO: correct encoding? start(); } From fae615a4702d0db7efc8e5120148370abc489fff Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Sun, 22 Feb 2015 13:46:14 +0300 Subject: [PATCH 120/231] Show "Optional actions" label only if there are any (IDEA-136830) --- .../src/com/intellij/codeInsight/actions/LayoutCodeDialog.form | 2 +- .../src/com/intellij/codeInsight/actions/LayoutCodeDialog.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form index b6e07f4c8a5b..3c6a16512e86 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.form @@ -107,7 +107,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java index 6dc2971b800c..cd0a9c0890f2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java @@ -51,6 +51,7 @@ public class LayoutCodeDialog extends DialogWrapper { private JPanel myActionsPanel; private JPanel myScopePanel; + private JLabel myOptionalLabel; private LayoutCodeOptions myRunOptions; @@ -127,6 +128,8 @@ public class LayoutCodeDialog extends DialogWrapper { if (canRearrangeCode) { myRearrangeCodeCb.setSelected(myLastRunOptions.isRearrangeCode(myFile.getLanguage())); } + + myOptionalLabel.setVisible(canOptimizeImports || canRearrangeCode); } @Nullable From f0556a4a657bc07b4b371b0f04359b5768be8b9e Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Sun, 22 Feb 2015 15:00:45 +0300 Subject: [PATCH 121/231] Do not show "Unnecessary fully qualified name" warning in javadocs if "fully qualify when not imported" is selected and fqn is not imported (IDEA-136680) --- ...necessaryFullyQualifiedNameInspection.java | 19 +++++++++++-------- .../DoubleQualify.java | 7 +++++++ .../Single.java | 5 +++++ .../expected.xml | 11 +++++++++++ ...ssaryFullyQualifiedNameInspectionTest.java | 2 +- 5 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index 28669193d19a..9961a7103f18 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -15,7 +15,6 @@ */ package com.siyeh.ig.style; -import com.intellij.codeInsight.javadoc.JavaDocUtil; import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.diagnostic.Logger; @@ -26,6 +25,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; +import com.intellij.psi.impl.source.codeStyle.ImportHelper; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -206,11 +206,6 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl if (element != null) { return; } - final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); - PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); - if (containingComment != null && acceptFullyQualifiedNamesInJavadoc(containingComment, styleSettings)) { - return; - } final PsiFile containingFile = reference.getContainingFile(); if (!(containingFile instanceof PsiJavaFile)) { return; @@ -219,6 +214,11 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl if (!(target instanceof PsiClass)) { return; } + final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); + PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); + if (containingComment != null && acceptFqnInJavadoc((PsiJavaFile)containingFile, reference.getQualifiedName(), styleSettings)) { + return; + } final PsiJavaCodeReferenceElement qualifierReference = (PsiJavaCodeReferenceElement)qualifier; final PsiElement qualifierTarget = qualifierReference.resolve(); if (!(qualifierTarget instanceof PsiPackage)) { @@ -262,11 +262,14 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl } } - public static boolean acceptFullyQualifiedNamesInJavadoc(PsiDocComment comment, CodeStyleSettings styleSettings) { - if (JavaDocUtil.isInsidePackageInfo(comment)) { + private static boolean acceptFqnInJavadoc(PsiJavaFile javaFile, String fullyQualifiedName, CodeStyleSettings styleSettings) { + if ("package-info.java".equals(javaFile.getName())) { return true; } JavaCodeStyleSettings javaSettings = styleSettings.getCustomSettings(JavaCodeStyleSettings.class); + if (javaSettings.CLASS_NAMES_IN_JAVADOC == JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED) { + return !ImportHelper.isAlreadyImported(javaFile, fullyQualifiedName); + } return javaSettings.useFqNamesInJavadocAlways(); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java new file mode 100644 index 000000000000..de1e31544974 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/DoubleQualify.java @@ -0,0 +1,7 @@ +import java.util.HashMap; + +/** + * {@link java.util.HashMap} + */ +public class DoubleQualify { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java new file mode 100644 index 000000000000..193c25f043c5 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/Single.java @@ -0,0 +1,5 @@ +/** + * {@link java.util.HashMap} + */ +public class Single { +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml new file mode 100644 index 000000000000..05706352d657 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fqn_javadoc_fully_qualify_if_not_imported/expected.xml @@ -0,0 +1,11 @@ + + + + + DoubleQualify.java + 4 + Unnecessary fully qualified name + Fully qualified name <code>java.util.HashMap</code> is unnecessary, and can be replaced with an import #loc + + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java index 8dc9ea7b861c..1856fc662a46 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java @@ -10,7 +10,7 @@ public class UnnecessaryFullyQualifiedNameInspectionTest extends IGInspectionTes private static final String BASE_DIR = "com/siyeh/igtest/style/"; public void testFqnInJavadoc_Unnecessary_WhenFullyQualifyIfNotImported() throws Exception { - doTestWithFqnInJavadocSetting(BASE_DIR + "unnecessary_fully_qualified_name/", JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED); + doTestWithFqnInJavadocSetting(BASE_DIR + "unnecessary_fqn_javadoc_fully_qualify_if_not_imported", JavaCodeStyleSettings.FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED); } public void testFqnInJavadoc_Unnecessary_WhenShortNamesAlways() { From f02dc6c4ed1f212bbf335510dccf37f7447e0cb2 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Sun, 22 Feb 2015 16:29:06 +0300 Subject: [PATCH 122/231] test fixed --- .../SuspiciousLanguagesInspectionTest.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java index 784b6e9ea737..891b8fcffe34 100644 --- a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java +++ b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java @@ -31,25 +31,20 @@ public class SuspiciousLanguagesInspectionTest extends LightCodeInsightFixtureTe } public void testSimple1() { - doTest(); + doTest("p.properties", "p_en.properties"); } public void testSimple2() { - doTest(); + doTest("p.properties", "p_asd.properties"); } public void testWithAdditionalLocales() { - doTest("asd"); + doTest("p.properties", "p_asd.properties", "asd"); } - private void doTest(final String... additionalLocales) { - final File tesDataDir = new File(getHomePath() + File.separator + getBasePath() + File.separator + getTestName(true)); - final File[] files = tesDataDir.listFiles(); - assertNotNull(files); - for (File file : files) { - final String path = file.getAbsolutePath(); - myFixture.configureByFile(path); - } + private void doTest(final String file1, final String file2, final String... additionalLocales) { + myFixture.configureByFile(getTestName(true) + "/" + file1); + myFixture.configureByFile(getTestName(true) + "/" + file2); final SuspiciousLocalesLanguagesInspection inspection = new SuspiciousLocalesLanguagesInspection(); if (additionalLocales.length != 0) { inspection.setAdditionalLanguages(ContainerUtil.newArrayList(additionalLocales)); From d565ab8d2c2a2db19b4a44d7cd1b98dd2f0c2aac Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Sun, 22 Feb 2015 21:06:10 +0300 Subject: [PATCH 123/231] SuspiciousLocalesLanguagesInspections: bundles with size < 2 ignored --- .../codeInspection/SuspiciousLocalesLanguagesInspection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java index b9ec80f1a5b5..e88d46649c4e 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java @@ -115,7 +115,7 @@ public class SuspiciousLocalesLanguagesInspection extends BaseLocalInspectionToo } final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); final List files = resourceBundle.getPropertiesFiles(); - if (files.isEmpty()) { + if (files.size() < 2) { return null; } List bundleLocales = ContainerUtil.mapNotNull(files, new Function() { From 3702e6990391e7ccb0ec8d1a3e39ef0796ca363a Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Sun, 22 Feb 2015 21:07:51 +0300 Subject: [PATCH 124/231] Slow updating of project view while resource bundle dissociation fixed --- .../DissociateResourceBundleAction.java | 14 +++++++++++++- .../properties/projectView/ResourceBundleNode.java | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java b/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java index b36be1746912..25c0be113f69 100644 --- a/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java +++ b/plugins/properties/src/com/intellij/lang/properties/customizeActions/DissociateResourceBundleAction.java @@ -17,6 +17,7 @@ package com.intellij.lang.properties.customizeActions; import com.intellij.icons.AllIcons; import com.intellij.ide.projectView.ProjectView; +import com.intellij.ide.util.treeView.AbstractTreeBuilder; import com.intellij.lang.properties.PropertiesImplUtil; import com.intellij.lang.properties.ResourceBundle; import com.intellij.lang.properties.ResourceBundleManager; @@ -27,12 +28,15 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; +import javax.swing.*; import java.util.*; /** @@ -73,14 +77,22 @@ public class DissociateResourceBundleAction extends AnAction { public static void dissociate(final Collection resourceBundles, final Project project) { final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); + final Set toUpdateInProjectView = new HashSet(); for (ResourceBundle resourceBundle : resourceBundles) { fileEditorManager.closeFile(new ResourceBundleAsVirtualFile(resourceBundle)); for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) { fileEditorManager.closeFile(propertiesFile.getVirtualFile()); + PsiDirectory containingDirectory = propertiesFile.getContainingFile().getContainingDirectory(); + if (containingDirectory != null) { + toUpdateInProjectView.add(containingDirectory); + } } ResourceBundleManager.getInstance(project).dissociateResourceBundle(resourceBundle); } - ProjectView.getInstance(project).refresh(); + AbstractTreeBuilder treeBuilder = ProjectView.getInstance(project).getCurrentProjectViewPane().getTreeBuilder(); + for (PsiFileSystemItem item : toUpdateInProjectView) { + treeBuilder.queueUpdateFrom(item, false); + } } @NotNull diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java index b9f61643095d..20af8439004c 100644 --- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java +++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleNode.java @@ -32,6 +32,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -97,4 +98,12 @@ public class ResourceBundleNode extends ProjectViewNode{ public Comparable getTypeSortKey() { return new PsiFileNode.ExtensionSortKey(StdFileTypes.PROPERTIES.getDefaultExtension()); } + + @Override + public boolean validate() { + if (!super.validate()) { + return false; + } + return Comparing.equal(getValue().getDefaultPropertiesFile().getResourceBundle(), getValue()); + } } From fba83a2a034099beac9fbad09f3a3ff213adb367 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Sun, 22 Feb 2015 21:17:28 +0300 Subject: [PATCH 125/231] SuspiciousLocalesLanguagesInspection: custom resource bundles ignored --- .../SuspiciousLocalesLanguagesInspection.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java index e88d46649c4e..1dc726b8a2ee 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java @@ -16,10 +16,8 @@ package com.intellij.codeInspection; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; -import com.intellij.lang.properties.PropertiesBundle; -import com.intellij.lang.properties.PropertiesImplUtil; +import com.intellij.lang.properties.*; import com.intellij.lang.properties.ResourceBundle; -import com.intellij.lang.properties.ResourceBundleManager; import com.intellij.lang.properties.customizeActions.DissociateResourceBundleAction; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.project.Project; @@ -115,7 +113,7 @@ public class SuspiciousLocalesLanguagesInspection extends BaseLocalInspectionToo } final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); final List files = resourceBundle.getPropertiesFiles(); - if (files.size() < 2) { + if (!(resourceBundle instanceof ResourceBundleImpl) || files.size() < 2) { return null; } List bundleLocales = ContainerUtil.mapNotNull(files, new Function() { From 4a60c5a05ccda93fb6abd42e323ed3f60a93485c Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 23 Feb 2015 01:16:11 +0300 Subject: [PATCH 126/231] inspection short name fixed --- plugins/java-i18n/src/META-INF/plugin.xml | 2 +- .../src/inspectionDescriptions/SuspiciousLocalesLanguages.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index 3f042db7095e..9d4fc9a8f356 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -54,7 +54,7 @@ enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.capitalization.TitleCapitalizationInspection"/> - -Inspection detects locales which contain languages not included supported by Java. +Inspection detects locales which contain language codes not supported by Java. \ No newline at end of file From ece86046575e8294351962ff7380f4f8ddf24e4d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Feb 2015 00:03:53 +0100 Subject: [PATCH 127/231] install system fonts for Darcula on Linux --- .../ide/ui/laf/darcula/DarculaLaf.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 390c0190c71d..8e9ca5a93e52 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -42,10 +42,8 @@ import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; -import java.util.Arrays; +import java.util.*; import java.util.List; -import java.util.Locale; -import java.util.Properties; /** * @author Konstantin Bulenkov @@ -56,7 +54,7 @@ public class DarculaLaf extends BasicLookAndFeel { public DarculaLaf() { try { - if (SystemInfo.isWindows) { + if (SystemInfo.isWindows || SystemInfo.isLinux) { base = new IdeaLaf(); } else { final String name = UIManager.getSystemLookAndFeelClassName(); @@ -82,7 +80,7 @@ public class DarculaLaf extends BasicLookAndFeel { @SuppressWarnings("UnusedParameters") private static void log(Exception e) { // everything is gonna be alright -// e.printStackTrace(); + e.printStackTrace(); } @Override @@ -91,6 +89,7 @@ public class DarculaLaf extends BasicLookAndFeel { final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults"); superMethod.setAccessible(true); final UIDefaults metalDefaults = (UIDefaults)superMethod.invoke(new MetalLookAndFeel()); + final UIDefaults defaults = (UIDefaults)superMethod.invoke(base); if (SystemInfo.isLinux) { if (!Registry.is("darcula.use.native.fonts.on.linux")) { @@ -124,6 +123,9 @@ public class DarculaLaf extends BasicLookAndFeel { if (SystemInfo.isWindows) { //JFrame.setDefaultLookAndFeelDecorated(true); } + if (SystemInfo.isLinux && JBUI.isHiDPI()) { + applySystemFonts(defaults); + } defaults.put("EditorPane.font", defaults.getFont("TextField.font")); return defaults; } @@ -133,6 +135,23 @@ public class DarculaLaf extends BasicLookAndFeel { return super.getDefaults(); } + private static void applySystemFonts(UIDefaults defaults) { + try { + String fqn = UIManager.getSystemLookAndFeelClassName(); + Object systemLookAndFeel = Class.forName(fqn).newInstance(); + final Method superMethod = BasicLookAndFeel.class.getDeclaredMethod("getDefaults"); + superMethod.setAccessible(true); + final UIDefaults systemDefaults = (UIDefaults)superMethod.invoke(systemLookAndFeel); + for (Map.Entry entry : systemDefaults.entrySet()) { + if (entry.getValue() instanceof Font) { + defaults.put(entry.getKey(), entry.getValue()); + } + } + } catch (Exception e) { + log(e); + } + } + protected DefaultMetalTheme createMetalTheme() { return new DarculaMetalTheme(); } From 34dd16ff20fec4f64a55b72ad8e5eef16d472958 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Feb 2015 00:04:38 +0100 Subject: [PATCH 128/231] do not redefine system fonts for IntelliJ Laf --- .../com/intellij/ide/ui/laf/IntelliJLaf.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java index 2df9bf7f6414..e1e77fb8354f 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,11 +15,8 @@ */ package com.intellij.ide.ui.laf; -import com.intellij.ide.ui.LafManager; import com.intellij.ide.ui.laf.darcula.DarculaLaf; -import com.intellij.openapi.util.SystemInfo; -import javax.swing.*; import javax.swing.plaf.metal.DefaultMetalTheme; /** @@ -36,19 +33,6 @@ public class IntelliJLaf extends DarculaLaf { return "intellijlaf"; } - @Override - public UIDefaults getDefaults() { - UIDefaults defaults = super.getDefaults(); - if (SystemInfo.isLinux) { - try { - LafManagerImpl.initFontDefaults(defaults, "Dialog", 12); - } - catch (Exception ignore) { - } - } - return defaults; - } - @Override protected DefaultMetalTheme createMetalTheme() { return new IdeaBlueMetalTheme(); From 45087294907b0751d3dc6cecf0284b0b4a8f0d8b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Feb 2015 00:55:46 +0100 Subject: [PATCH 129/231] HiDPI: don't patch int values twice in UIDefaults --- .../src/com/intellij/ide/ui/laf/LafManagerImpl.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index 779e326d2802..0a2ce8d93e67 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -560,6 +560,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo List myIntKeys = Arrays.asList("Tree.leftChildIndent", "Tree.rightChildIndent"); + List patched = new ArrayList(); for (Map.Entry entry : defaults.entrySet()) { Object value = entry.getValue(); String key = entry.getKey().toString(); @@ -569,10 +570,16 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo entry.setValue(JBUI.insets(((InsetsUIResource)value)).asUIResource()); } else if (value instanceof Integer) { if (key.endsWith(".maxGutterIconWidth") || myIntKeys.contains(key)) { - entry.setValue(Integer.valueOf(JBUI.scale((Integer)value))); + if (!"true".equals(defaults.get(key +".hidpi.patched"))) { + entry.setValue(Integer.valueOf(JBUI.scale((Integer)value))); + patched.add(key); + } } } } + for (String key : patched) { + defaults.put(key + ".hidpi.patched", "true"); + } } public static void updateToolWindows() { From 3c97e2381f0dcbe9ea598daaa1c80fd9e6b9f39b Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Mon, 23 Feb 2015 09:06:22 +0300 Subject: [PATCH 130/231] temporary reverting fix for IDEA-136763 Need to provide at least one implementation for the ext point to avoid IAE --- .../sm/runner/ui/SMTRunnerNotificationsHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java index 7b4a539a4721..b8e276354945 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java @@ -99,7 +99,8 @@ public class SMTRunnerNotificationsHandler extends SMTRunnerEventsAdapter { type = null; } - TestStatusListener.notifySuiteFinished(testsRoot, myConsoleProperties.getProject()); + // todo: need to provide default implementation before notifying test status listeners to avoid IAE + //TestStatusListener.notifySuiteFinished(testsRoot, myConsoleProperties.getProject()); if (msg != null) { notify(msg, type, testsRoot); From dde5c62b039c6a10d1ae07f4efde0c880f2cf82a Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 07:25:07 +0100 Subject: [PATCH 131/231] should be trimTrailingSlashes --- .../debugger/sourcemap/SourceMapDecoder.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java index 397e04ef9f59..cf4d40ab9eb7 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.debugger.sourcemap; import com.google.gson.stream.JsonToken; @@ -98,7 +113,7 @@ public final class SourceMapDecoder { else if (propertyName.equals("sourceRoot")) { sourceRoot = readSourcePath(reader); if (sourceRoot != null) { - sourceRoot = UriUtil.trimLeadingSlashes(sourceRoot); + sourceRoot = UriUtil.trimTrailingSlashes(sourceRoot); } } else if (propertyName.equals("sources")) { From 81cc78393f8efee915b579474addbf4f01217da6 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 07:41:06 +0100 Subject: [PATCH 132/231] load defaults for LanguageInjectionConfiguration --- .../openapi/components/impl/stores/ComponentStoreImpl.java | 5 +++++ .../src/org/intellij/plugins/intelliLang/Configuration.java | 2 ++ 2 files changed, 7 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 5e78e340a581..fef8f4f8bac6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -281,6 +281,11 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } Class stateClass = ComponentSerializationUtil.getStateClass(component.getClass()); + // todo remove assert before last EAP + if (!stateSpec.defaultStateAsResource() && getDefaultState(component, name, stateClass) != null) { + LOG.error(name + " has default state, but not marked to load it"); + } + T state = stateSpec.defaultStateAsResource() ? getDefaultState(component, name, stateClass) : null; Storage[] storageSpecs = getComponentStorageSpecs(component, stateSpec, StateStorageOperation.READ); for (Storage storageSpec : storageSpecs) { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java index b2bfefce47e6..a2d910570ae5 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java @@ -76,6 +76,7 @@ public class Configuration extends SimpleModificationTracker implements Persiste @State( name = Configuration.COMPONENT_NAME, + defaultStateAsResource = true, storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/IntelliLang.xml", scheme = StorageScheme.DIRECTORY_BASED)}) public static class App extends Configuration { @@ -110,6 +111,7 @@ public class Configuration extends SimpleModificationTracker implements Persiste return getState(element); } } + @State( name = Configuration.COMPONENT_NAME, storages = { From 9856395be237181b62bd7a1bcdfb861d37e775e5 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 09:22:44 +0100 Subject: [PATCH 133/231] cleanup --- .../codeInsight/template/impl/TemplateSettings.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java index c7c05dc68d74..3f644c04fd39 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java @@ -452,12 +452,10 @@ public class TemplateSettings implements PersistentStateComponent Date: Mon, 23 Feb 2015 09:29:48 +0100 Subject: [PATCH 134/231] Prj requires defaults --- .../src/org/intellij/plugins/intelliLang/Configuration.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java index a2d910570ae5..8db552b12ee6 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java @@ -114,6 +114,7 @@ public class Configuration extends SimpleModificationTracker implements Persiste @State( name = Configuration.COMPONENT_NAME, + defaultStateAsResource = true, storages = { @Storage(file = StoragePathMacros.PROJECT_FILE), @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/IntelliLang.xml", scheme = StorageScheme.DIRECTORY_BASED) From bcf9306f1b82bef76372c171581a23fee41d9161 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 09:32:50 +0100 Subject: [PATCH 135/231] Palette2 defaults --- .../ui-designer/src/com/intellij/uiDesigner/palette/Palette.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java index abe744594ca7..4627efd195f0 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java @@ -65,6 +65,7 @@ import java.util.Map; */ @State( name = "Palette2", + defaultStateAsResource = true, storages = { @Storage(file = StoragePathMacros.PROJECT_FILE), @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/uiDesigner.xml", scheme = StorageScheme.DIRECTORY_BASED) From e3d0a83c8cecf7076a7d5bc889dbf79a116fbf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Mon, 23 Feb 2015 10:51:21 +0100 Subject: [PATCH 136/231] InspectionValidator#getProcessingItems: make sure to run in smart mode (EA-63972) [r=peter] --- .../util/InspectionValidatorWrapper.java | 68 +++++++++---------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java b/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java index 4868321f9ca2..9d34478d9e53 100644 --- a/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java +++ b/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -29,13 +29,11 @@ import com.intellij.lang.annotation.AnnotationSession; import com.intellij.lang.annotation.ExternalAnnotator; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.application.ReadActionProcessor; -import com.intellij.openapi.application.Result; import com.intellij.openapi.compiler.*; import com.intellij.openapi.compiler.options.ExcludesConfiguration; import com.intellij.openapi.editor.Document; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; @@ -143,41 +141,41 @@ public class InspectionValidatorWrapper implements Validator { return ProcessingItem.EMPTY_ARRAY; } final ExcludesConfiguration excludesConfiguration = ValidationConfiguration.getExcludedEntriesConfiguration(project); - final List items = new ReadAction>() { - @Override - protected void run(final Result> result) { - final CompileScope compileScope = context.getCompileScope(); - if (!myValidator.isAvailableOnScope(compileScope)) return; + final List items = + DumbService.getInstance(project).runReadActionInSmartMode(new Computable>() { + @Override + public List compute() { + final CompileScope compileScope = context.getCompileScope(); + if (!myValidator.isAvailableOnScope(compileScope)) return null; - final ArrayList items = new ArrayList(); + final ArrayList items = new ArrayList(); - final Processor processor = new ReadActionProcessor() { - @Override - public boolean processInReadAction(VirtualFile file) { - if (!file.isValid()) { - return true; - } - - if (myCompilerManager.isExcludedFromCompilation(file) || - excludesConfiguration.isExcluded(file)) { - return true; - } - - final Module module = context.getModuleByFile(file); - if (module != null) { - final PsiFile psiFile = myPsiManager.findFile(file); - if (psiFile != null) { - items.add(new MyValidatorProcessingItem(psiFile)); + final Processor processor = new Processor() { + @Override + public boolean process(VirtualFile file) { + if (!file.isValid()) { + return true; } - } - return true; - } - }; - ContainerUtil.process(myValidator.getFilesToProcess(myPsiManager.getProject(), context), processor); - result.setResult(items); - } - }.execute().getResultObject(); + if (myCompilerManager.isExcludedFromCompilation(file) || + excludesConfiguration.isExcluded(file)) { + return true; + } + + final Module module = context.getModuleByFile(file); + if (module != null) { + final PsiFile psiFile = myPsiManager.findFile(file); + if (psiFile != null) { + items.add(new MyValidatorProcessingItem(psiFile)); + } + } + return true; + } + }; + ContainerUtil.process(myValidator.getFilesToProcess(myPsiManager.getProject(), context), processor); + return items; + } + }); if (items == null) return ProcessingItem.EMPTY_ARRAY; return items.toArray(new ProcessingItem[items.size()]); From f64efe9dcc2634d05173890caac6dc257d218390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Mon, 23 Feb 2015 11:05:37 +0100 Subject: [PATCH 137/231] PatternPackageReferenceSet: cleanup, copyright, linked Set --- .../providers/PatternPackageReferenceSet.java | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java index 392cacfb2ac9..ef1085f32bb6 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java @@ -1,19 +1,35 @@ +/* + * Copyright 2000-2015 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.psi.impl.source.resolve.reference.impl.providers; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPackage; -import com.intellij.psi.impl.source.resolve.reference.impl.providers.PackageReferenceSet; import com.intellij.util.PatternUtil; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import java.util.regex.Pattern; public class PatternPackageReferenceSet extends PackageReferenceSet { + public PatternPackageReferenceSet(String packageName, PsiElement element, int startInElement) { super(packageName, element, startInElement); } @@ -24,7 +40,7 @@ public class PatternPackageReferenceSet extends PackageReferenceSet { if (packageName.contains("*")) { final Pattern pattern = PatternUtil.fromMask(packageName); - final Set packages = new HashSet(); + final Set packages = new LinkedHashSet(); processSubPackages(context, new Processor() { @Override @@ -39,16 +55,13 @@ public class PatternPackageReferenceSet extends PackageReferenceSet { return packages; } - else { - return super.resolvePackageName(context, packageName); - } + + return super.resolvePackageName(context, packageName); } - protected static boolean processSubPackages(final PsiPackage pkg, final Processor processor) { + protected static boolean processSubPackages(final PsiPackage pkg, final Processor processor) { if (!processor.process(pkg)) return false; - for (final PsiPackage aPackage : pkg.getSubPackages()) { - if (!processSubPackages(aPackage, processor)) return false; - } - return true; + + return ContainerUtil.process(pkg.getSubPackages(), processor); } } From 66d6841e0bc16932815501e27a55da67ae03dfb5 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 23 Feb 2015 11:10:57 +0100 Subject: [PATCH 138/231] [performance optimization] iterate over Map's values() directly, avoid (WeakKey)Map.get() --- .../openapi/file/exclude/EnforcedPlainTextFileTypeManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java index 9526e0c597f9..40d4640133aa 100644 --- a/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/file/exclude/EnforcedPlainTextFileTypeManager.java @@ -58,8 +58,7 @@ public class EnforcedPlainTextFileTypeManager implements ProjectManagerListener } } } - for (Project project : myPlainTextFileSets.keySet()) { - Collection projectSet = myPlainTextFileSets.get(project); + for (Collection projectSet : myPlainTextFileSets.values()) { if (projectSet != null && projectSet.contains(file)) return true; } return false; From acfac818aebaa9a901ffc994e36da0f79aa4e557 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 23 Feb 2015 11:12:38 +0100 Subject: [PATCH 139/231] [performance optimization] store service impl in holder --- .../src/com/intellij/ide/scratch/ScratchFileService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java index fef6554ca238..46075f81f4ae 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileService.java @@ -29,7 +29,11 @@ public abstract class ScratchFileService { public enum Option { existing_only, create_if_missing, create_new_always } public static ScratchFileService getInstance() { - return ServiceManager.getService(ScratchFileService.class); + return ServiceHolder.instance; + } + + private static class ServiceHolder { + static final ScratchFileService instance = ServiceManager.getService(ScratchFileService.class); } @NotNull From eec068545660be3480a269281d33816c5042edaa Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 23 Feb 2015 11:14:40 +0100 Subject: [PATCH 140/231] [performance optimization] no equals / hashCode invokations for V during deserialization --- .../util/indexing/ValueContainerImpl.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index 55586b5e8b76..f80786273af7 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -390,8 +390,8 @@ class ValueContainerImpl extends UpdatableValueContainer implement return container; } - private void ensureFileSetCapacityForValue(Value value, int count) { - if (count <= 1) return; + private @Nullable ChangeBufferingList ensureFileSetCapacityForValue(Value value, int count) { + if (count <= 1) return null; Object fileSetObject = getFileSetObject(value); if (fileSetObject != null) { @@ -399,15 +399,18 @@ class ValueContainerImpl extends UpdatableValueContainer implement ChangeBufferingList list = new ChangeBufferingList(count + 1); list.add(((Integer)fileSetObject).intValue()); resetFileSetForValue(value, list); + return list; } else if (fileSetObject instanceof ChangeBufferingList) { ChangeBufferingList list = (ChangeBufferingList)fileSetObject; list.ensureCapacity(count); + return list; } - return; + return null; } - final Object fileSet = new ChangeBufferingList(count); + final ChangeBufferingList fileSet = new ChangeBufferingList(count); attachFileSetForNewValue(value, fileSet); + return fileSet; } private void attachFileSetForNewValue(Value value, Object fileSet) { @@ -551,12 +554,13 @@ class ValueContainerImpl extends UpdatableValueContainer implement if (mapping != null) mapping.associateFileIdToValue(idCountOrSingleValue, value); } else { idCountOrSingleValue = -idCountOrSingleValue; - ensureFileSetCapacityForValue(value, idCountOrSingleValue); + ChangeBufferingList changeBufferingList = ensureFileSetCapacityForValue(value, idCountOrSingleValue); int prev = 0; for (int i = 0; i < idCountOrSingleValue; i++) { final int id = DataInputOutputUtil.readINT(stream); - addValue(prev + id, value); + if (changeBufferingList != null) changeBufferingList.add(prev + id); + else addValue(prev + id, value); if (mapping != null) mapping.associateFileIdToValue(prev + id, value); prev += id; } From 7d698151c061515438acff5c07ce9e26c0a56fbe Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Mon, 23 Feb 2015 12:40:46 +0300 Subject: [PATCH 141/231] EA-64930 --- .../codeInsight/editorActions/XmlTagNameSynchronizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java index b41845573d7f..18427c96c96c 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java @@ -102,7 +102,7 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio } private static Language findXmlLikeLanguage(Project project, VirtualFile file) { - final PsiFile psiFile = file != null ? PsiManager.getInstance(project).findFile(file) : null; + final PsiFile psiFile = file != null && file.isValid() ? PsiManager.getInstance(project).findFile(file) : null; if (psiFile != null) { for (Language language : psiFile.getViewProvider().getLanguages()) { if (SUPPORTED_LANGUAGES.contains(language.getID())) return language; From ad56e564e63d64e27e2a3babbe2bdd3fd6ffcb47 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 09:34:58 +0100 Subject: [PATCH 142/231] cleanup --- .../src/com/intellij/diff/DiffManagerImpl.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java index b71a7e5e4f78..816ea9595797 100644 --- a/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/DiffManagerImpl.java @@ -26,7 +26,6 @@ import com.intellij.diff.tools.external.ExternalDiffTool; import com.intellij.diff.tools.fragmented.OnesideDiffTool; import com.intellij.diff.tools.simple.SimpleDiffTool; import com.intellij.openapi.Disposable; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.NotNull; @@ -34,11 +33,10 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class DiffManagerImpl extends DiffManagerEx { - private static final Logger LOG = Logger.getInstance(DiffManagerImpl.class); - @Override public void showDiff(@Nullable Project project, @NotNull DiffRequest request) { showDiff(project, request, DiffDialogHints.DEFAULT); @@ -88,16 +86,11 @@ public class DiffManagerImpl extends DiffManagerEx { @Override public List getDiffTools() { List result = new ArrayList(); - result.add(SimpleDiffTool.INSTANCE); result.add(OnesideDiffTool.INSTANCE); result.add(BinaryDiffTool.INSTANCE); result.add(DirDiffTool.INSTANCE); - - for (DiffTool tool : DiffTool.EP_NAME.getExtensions()) { - result.add(tool); - } - + Collections.addAll(result, DiffTool.EP_NAME.getExtensions()); return result; } } From 392d15f11b0deb4f8ed3167e9a57c55205891f9d Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 09:36:21 +0100 Subject: [PATCH 143/231] cleanup --- .../intellij/openapi/diff/DiffManager.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java index 1a631eae0b79..8c7f7905ff13 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; public abstract class DiffManager { - public static DiffManager getInstance() { return ServiceManager.getService(DiffManager.class); } @@ -37,15 +36,15 @@ public abstract class DiffManager { * {@link DiffTool#HINT_SHOW_MODAL_DIALOG} force show diff in modal dialog
    * {@link DiffTool#HINT_SHOW_FRAME} don't check modal window open. * Show diff in frame in any case. May help as workaround when closing - * modal dialog right before openning diff.
    + * modal dialog right before opening diff.
    * {@link DiffTool#HINT_SHOW_NOT_MODAL_DIALOG} Show diff in not modal dialog
    */ public abstract DiffTool getIdeaDiffTool(); /** - * Work in progess. Don't rely on this functionality
    + * Work in progress. Don't rely on this functionality
    * Adds new diff tool. - * + * * @param tool diff tool to register * @return false iff tool already registered (tool won't be registered twice). Otherwise true. * @throws NullPointerException iff tool == null @@ -53,9 +52,9 @@ public abstract class DiffManager { public abstract boolean registerDiffTool(DiffTool tool) throws NullPointerException; /** - * Work in progess. Don't rely on this functionality
    - * Unregisters tool, registered with {@link #registerDiffTool(DiffTool)} - * + * Work in progress. Don't rely on this functionality
    + * Unregister tool, registered with {@link #registerDiffTool(DiffTool)} + * * @param tool diff tool to unregister */ public abstract void unregisterDiffTool(DiffTool tool); @@ -63,12 +62,11 @@ public abstract class DiffManager { public abstract MarkupEditorFilter getDiffEditorFilter(); /** - * - * @param window this window will be disposed, when user clicks on the line number - * You must call Disposer.dispose() when done. - * @param disposable - *@param parentTool @deprecated use {@link #createDiffPanel(Window, Project, Disposable)} instead + * @param window this window will be disposed, when user clicks on the line number + * You must call Disposer.dispose() when done. + * @param parentTool @deprecated use {@link #createDiffPanel(Window, Project, Disposable)} instead */ public abstract DiffPanel createDiffPanel(Window window, @NotNull Project project, DiffTool parentTool); + public abstract DiffPanel createDiffPanel(Window window, @NotNull Project project, @NotNull Disposable parentDisposable, DiffTool parentTool); } From f9174b74f05efc381b83dd9a8048750f94bb34be Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 11:18:33 +0100 Subject: [PATCH 144/231] DiffManagerImpl should be persistent component, don't save defaults (COMPARISON_POLICY="Default") --- .../util/config/AbstractProperty.java | 26 ++-- .../ExternalizablePropertyContainer.java | 63 +++++----- .../intellij/util/config/Externalizer.java | 37 +++--- .../intellij/openapi/diff/ex/DiffPanelEx.java | 4 +- .../openapi/diff/impl/DiffPanelImpl.java | 23 ++-- .../diff/impl/external/CompositeDiffTool.java | 14 ++- .../diff/impl/external/DiffManagerImpl.java | 119 +++++++++++------- .../diff/impl/external/FrameDiffTool.java | 45 ++++--- .../highlighting/SimpleDiffPanelState.java | 9 +- .../openapi/diff/impl/ComparisonPolicy.java | 8 +- .../FragmentedDiffRequestFromChange.java | 20 ++- .../ant/config/impl/AllJarsUnderDirEntry.java | 5 +- .../ant/config/impl/AntClasspathEntry.java | 20 +-- .../lang/ant/config/impl/AntInstallation.java | 10 +- .../lang/ant/config/impl/AntReference.java | 9 +- .../config/impl/GlobalAntConfiguration.java | 19 +-- .../lang/ant/config/impl/SinglePathEntry.java | 8 +- 17 files changed, 238 insertions(+), 201 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java b/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java index 4c46e2362e33..97b6e4d882c6 100644 --- a/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java +++ b/platform/platform-api/src/com/intellij/util/config/AbstractProperty.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.config; import com.intellij.openapi.util.Comparing; @@ -28,17 +27,28 @@ public abstract class AbstractProperty { } }; - @NonNls public abstract String getName(); + @NonNls + public abstract String getName(); + public abstract T getDefault(AbstractPropertyContainer container); + public abstract T copy(T value); public boolean areEqual(T value1, T value2) { return Comparing.equal(value1, value2); } - public T get(AbstractPropertyContainer container) { return (T) container.getValueOf(this); } - public void set(AbstractPropertyContainer container, T value) { container.setValueOf(this, value); } - public final T cast(Object value) { return (T) value; } + public T get(AbstractPropertyContainer container) { + return (T)container.getValueOf(this); + } + + public void set(AbstractPropertyContainer container, T value) { + container.setValueOf(this, value); + } + + public final T cast(Object value) { + return (T)value; + } public String toString() { return getName(); @@ -60,7 +70,9 @@ public abstract class AbstractProperty { }; protected abstract Object getValueOf(PropertyImpl property); + protected abstract void setValueOf(PropertyImpl property, Object value); + public abstract boolean hasProperty(AbstractProperty property); /** @@ -73,7 +85,7 @@ public abstract class AbstractProperty { /** * Only containers can delegate to another. - * Other clients should use {@link AbstractProperty#get AbstractProperty.get} + * Other clients should use {@link AbstractProperty#get AbstractProperty.get} */ protected final T delegateGet(AbstractPropertyContainer container, AbstractProperty property) { return (T)container.getValueOf(property); diff --git a/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java b/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java index 3f48ecf2a4b1..25f3a173e45b 100644 --- a/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java +++ b/platform/platform-api/src/com/intellij/util/config/ExternalizablePropertyContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,20 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.config; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.SmartList; +import gnu.trove.THashMap; import org.jdom.Element; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; -public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPropertyContainer implements JDOMExternalizable { +public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPropertyContainer { private static final Logger LOG = Logger.getInstance(ExternalizablePropertyContainer.class); - private final Map myValues = new HashMap(); - private final Map myExternalizers = new HashMap(); + private final Map myValues = new THashMap(); + private final Map myExternalizers = new THashMap(); public void registerProperty(AbstractProperty property, Externalizer externalizer) { String name = property.getName(); @@ -66,37 +74,34 @@ public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPr registerProperty(property, itemTagName, Externalizer.FactoryBased.create(factory)); } - private Externalizer> createListExternalizer(final Externalizer itemExternalizer, final String itemTagName) { + private static Externalizer> createListExternalizer(final Externalizer itemExternalizer, final String itemTagName) { return new ListExternalizer(itemExternalizer, itemTagName); } - @Override - public void readExternal(Element element) throws InvalidDataException { - HashMap propertyByName = new HashMap(); + public void readExternal(@NotNull Element element) { + Map propertyByName = new THashMap(); for (AbstractProperty abstractProperty : myExternalizers.keySet()) { propertyByName.put(abstractProperty.getName(), abstractProperty); } - final List children = element.getChildren(); - for (Element child : children) { + for (Element child : element.getChildren()) { AbstractProperty property = propertyByName.get(child.getName()); if (property == null) { continue; } - final Externalizer externalizer = myExternalizers.get(property); + Externalizer externalizer = myExternalizers.get(property); if (externalizer == null) { continue; } try { myValues.put(property, externalizer.readValue(child)); } - catch (InvalidDataException e) { + catch (Exception e) { LOG.info(e); } } } - @Override - public void writeExternal(Element element) throws WriteExternalException { + public void writeExternal(@NotNull Element element) { if (myExternalizers.isEmpty()) { return; } @@ -147,12 +152,12 @@ public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPr } @Override - public List readValue(Element dataElement) throws InvalidDataException { - ArrayList list = new ArrayList(); - List children = dataElement.getChildren(); - for (Iterator iterator = children.iterator(); iterator.hasNext();) { - Element element = iterator.next(); - if (NULL_ELEMENT.equals(element.getName())) list.add(null); + public List readValue(Element dataElement) { + List list = new SmartList(); + for (Element element : dataElement.getChildren()) { + if (NULL_ELEMENT.equals(element.getName())) { + list.add(null); + } else if (myItemTagName.equals(element.getName())) { T item = myItemExternalizer.readValue(element); if (item == null) { @@ -166,17 +171,17 @@ public class ExternalizablePropertyContainer extends AbstractProperty.AbstractPr } @Override - public void writeValue(Element dataElement, List value) throws WriteExternalException { - for (Iterator iterator = value.iterator(); iterator.hasNext();) { - T item = iterator.next(); - if (item != null) { + public void writeValue(Element dataElement, List value) { + for (T item : value) { + if (item == null) { + dataElement.addContent(new Element(NULL_ELEMENT)); + } + else { Element element = new Element(myItemTagName); myItemExternalizer.writeValue(element, item); dataElement.addContent(element); } - else dataElement.addContent(new Element(NULL_ELEMENT)); } } } - } diff --git a/platform/platform-api/src/com/intellij/util/config/Externalizer.java b/platform/platform-api/src/com/intellij/util/config/Externalizer.java index 864b5bee0e43..1fb3eca0b262 100644 --- a/platform/platform-api/src/com/intellij/util/config/Externalizer.java +++ b/platform/platform-api/src/com/intellij/util/config/Externalizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import java.util.Iterator; -import java.util.List; public interface Externalizer { @NonNls String VALUE_ATTRIBUTE = "value"; @@ -60,9 +59,9 @@ public interface Externalizer { } }; - T readValue(Element dataElement) throws InvalidDataException; + T readValue(Element dataElement); - void writeValue(Element dataElement, T value) throws WriteExternalException; + void writeValue(Element dataElement, T value); class FactoryBased implements Externalizer { private final Factory myFactory; @@ -72,15 +71,25 @@ public interface Externalizer { } @Override - public T readValue(Element dataElement) throws InvalidDataException { + public T readValue(Element dataElement) { T data = myFactory.create(); - data.readExternal(dataElement); + try { + data.readExternal(dataElement); + } + catch (InvalidDataException e) { + throw new RuntimeException(e); + } return data; } @Override - public void writeValue(Element dataElement, T value) throws WriteExternalException { - value.writeExternal(dataElement); + public void writeValue(Element dataElement, T value) { + try { + value.writeExternal(dataElement); + } + catch (WriteExternalException e) { + throw new RuntimeException(e); + } } public static FactoryBased create(Factory factory) { @@ -94,25 +103,25 @@ public interface Externalizer { @NonNls private static final String VALUE_ATTR = "value"; @Override - public Storage readValue(Element dataElement) throws InvalidDataException { + public Storage readValue(Element dataElement) { Storage.MapStorage storage = new Storage.MapStorage(); - List children = dataElement.getChildren(ITEM_TAG); - for (Iterator iterator = children.iterator(); iterator.hasNext();) { - Element element = iterator.next(); + for (Element element : dataElement.getChildren(ITEM_TAG)) { storage.put(element.getAttributeValue(KEY_ATTR), element.getAttributeValue(VALUE_ATTR)); } return storage; } @Override - public void writeValue(Element dataElement, Storage storage) throws WriteExternalException { + public void writeValue(Element dataElement, Storage storage) { Iterator keys = ((Storage.MapStorage)storage).getKeys(); while (keys.hasNext()) { String key = keys.next(); String value = storage.get(key); Element element = new Element(ITEM_TAG); element.setAttribute(KEY_ATTR, key); - if (value != null) element.setAttribute(VALUE_ATTR, value); + if (value != null) { + element.setAttribute(VALUE_ATTR, value); + } dataElement.addContent(element); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java index bf07a4ad2cd1..7eb8000a7af3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -40,7 +40,7 @@ public interface DiffPanelEx extends DiffPanel, Disposable { DiffPanelOptions getOptions(); - void setComparisonPolicy(ComparisonPolicy comparisonPolicy); + void setComparisonPolicy(@NotNull ComparisonPolicy comparisonPolicy); ComparisonPolicy getComparisonPolicy(); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 7d1183a233c9..fbdde51e8761 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -180,17 +180,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid myDataProvider = new MyGenericDataProvider(this); myPanel.setDataProvider(myDataProvider); - final ComparisonPolicy comparisonPolicy = getComparisonPolicy(); - final ComparisonPolicy defaultComparisonPolicy = DiffManagerImpl.getInstanceEx().getComparisonPolicy(); - final HighlightMode highlightMode = getHighlightMode(); - final HighlightMode defaultHighlightMode = DiffManagerImpl.getInstanceEx().getHighlightMode(); + ComparisonPolicy comparisonPolicy = getComparisonPolicy(); + if (comparisonPolicy != DiffManagerImpl.getInstanceEx().getComparisonPolicy()) { + setComparisonPolicy(comparisonPolicy); + } - if (defaultComparisonPolicy != null && comparisonPolicy != defaultComparisonPolicy) { - setComparisonPolicy(defaultComparisonPolicy); - } - if (defaultHighlightMode != null && highlightMode != defaultHighlightMode) { - setHighlightMode(defaultHighlightMode); + HighlightMode highlightMode = getHighlightMode(); + if (highlightMode != DiffManagerImpl.getInstanceEx().getHighlightMode()) { + setHighlightMode(highlightMode); } + myVisibleAreaListener = new VisibleAreaListener() { @Override public void visibleAreaChanged(VisibleAreaEvent e) { @@ -504,11 +503,11 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid return myData.getComparisonPolicy(); } - public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) { + public void setComparisonPolicy(@NotNull ComparisonPolicy comparisonPolicy) { setComparisonPolicy(comparisonPolicy, true); } - private void setComparisonPolicy(ComparisonPolicy policy, boolean notifyManager) { + private void setComparisonPolicy(@NotNull ComparisonPolicy policy, boolean notifyManager) { myData.setComparisonPolicy(policy); rediff(); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java index d4948e11ee1a..15d51eec5d28 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,7 +18,10 @@ package com.intellij.openapi.diff.impl.external; import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.*; +import com.intellij.openapi.diff.DiffContent; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.DiffTool; +import com.intellij.openapi.diff.DiffViewer; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.UIBasedFileType; import org.jetbrains.annotations.NotNull; @@ -26,16 +29,21 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; class CompositeDiffTool implements DiffTool { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.external.CompositeDiffTool"); private final List myTools; - public CompositeDiffTool(List tools) { + public CompositeDiffTool(@NotNull List tools) { myTools = new ArrayList(tools); } + public CompositeDiffTool(@NotNull DiffTool[] tools) { + myTools = Arrays.asList(tools); + } + public void show(DiffRequest data) { checkDiffData(data); DiffTool tool = chooseTool(data); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java index aeb362bf68fe..2a842e99041d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,6 +16,10 @@ package com.intellij.openapi.diff.impl.external; import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.DiffManager; import com.intellij.openapi.diff.DiffPanel; @@ -29,8 +33,11 @@ import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.markup.MarkupEditorFilter; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; +import com.intellij.util.SmartList; import com.intellij.util.config.*; +import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -39,8 +46,16 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { +@State( + name = "DiffManager", + storages = { + @Storage(file = StoragePathMacros.APP_CONFIG + "/diff.xml"), + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true) + } +) +public class DiffManagerImpl extends DiffManager implements PersistentStateComponent { public static final int FULL_DIFF_DIVIDER_POLYGONS_OFFSET = 3; private static final Logger LOG = Logger.getInstance(DiffManagerImpl.class); @@ -50,7 +65,10 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { @Override public String readValue(Element dataElement) { String path = dataElement.getAttributeValue(NEW_VALUE); - if (path != null) return path; + if (path != null) { + return path; + } + String prevValue = dataElement.getAttributeValue(VALUE_ATTRIBUTE); return prevValue != null ? prevValue.trim() : null; } @@ -70,9 +88,8 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { public static final BooleanProperty ENABLE_FILES = new BooleanProperty("enableFiles", false); public static final BooleanProperty ENABLE_MERGE = new BooleanProperty("enableMerge", false); - private final ExternalizablePropertyContainer myProperties; - private final ArrayList myAdditionTools = new ArrayList(); + private final List myAdditionTools = new SmartList(); public static final DiffTool INTERNAL_DIFF = new FrameDiffTool(); public static final Key EDITOR_IS_DIFF_KEY = new Key("EDITOR_IS_DIFF_KEY"); @@ -82,8 +99,9 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { return DiffUtil.isDiffEditor(editor); } }; - private ComparisonPolicy myComparisonPolicy; - private HighlightMode myHighlightMode; + + private ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT; + private HighlightMode myHighlightMode = HighlightMode.BY_WORD; @NonNls public static final String COMPARISON_POLICY_ATTR_NAME = "COMPARISON_POLICY"; @NonNls public static final String HIGHLIGHT_MODE_ATTR_NAME = "HIGHLIGHT_MODE"; @@ -100,13 +118,15 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { } @Override - public DiffTool getIdeaDiffTool() { return INTERNAL_DIFF; } + public DiffTool getIdeaDiffTool() { + return INTERNAL_DIFF; + } @Override public DiffTool getDiffTool() { DiffTool[] standardTools; // there is inner check in multiple tool for external viewers as well - if (! ENABLE_FILES.value(myProperties) || ! ENABLE_FOLDERS.value(myProperties) || !ENABLE_MERGE.value(myProperties)) { + if (!ENABLE_FILES.value(myProperties) || !ENABLE_FOLDERS.value(myProperties) || !ENABLE_MERGE.value(myProperties)) { DiffTool[] embeddableTools = { INTERNAL_DIFF, new MergeTool(), @@ -121,7 +141,8 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { new MergeTool(), BinaryDiffTool.INSTANCE }; - } else { + } + else { standardTools = new DiffTool[]{ ExtCompareFolders.INSTANCE, ExtCompareFiles.INSTANCE, @@ -131,14 +152,22 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { BinaryDiffTool.INSTANCE }; } - ArrayList allTools = new ArrayList(myAdditionTools); - allTools.addAll(Arrays.asList(standardTools)); - return new CompositeDiffTool(allTools); + if (myAdditionTools.isEmpty()) { + return new CompositeDiffTool(standardTools); + } + else { + List allTools = new ArrayList(myAdditionTools); + ContainerUtil.addAll(allTools, standardTools); + return new CompositeDiffTool(allTools); + } } @Override public boolean registerDiffTool(@NotNull DiffTool tool) throws NullPointerException { - if (myAdditionTools.contains(tool)) return false; + if (myAdditionTools.contains(tool)) { + return false; + } + myAdditionTools.add(tool); return true; } @@ -149,7 +178,7 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { LOG.assertTrue(!myAdditionTools.contains(tool)); } - public ArrayList getAdditionTools() { + public List getAdditionTools() { return myAdditionTools; } @@ -174,28 +203,35 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { return (DiffManagerImpl)DiffManager.getInstance(); } + @Nullable @Override - public void readExternal(@NotNull Element element) throws InvalidDataException { - myProperties.readExternal(element); - readPolicy(element); - readMode(element); + public Element getState() { + Element state = new Element("state"); + myProperties.writeExternal(state); + if (myComparisonPolicy != ComparisonPolicy.DEFAULT) { + state.setAttribute(COMPARISON_POLICY_ATTR_NAME, myComparisonPolicy.getName()); + } + if (myHighlightMode != HighlightMode.BY_WORD) { + state.setAttribute(HIGHLIGHT_MODE_ATTR_NAME, myHighlightMode.name()); + } + return state; } - private void readPolicy(@NotNull final Element element) { - final String policyName = element.getAttributeValue(COMPARISON_POLICY_ATTR_NAME); + @Override + public void loadState(Element state) { + myProperties.readExternal(state); + + String policyName = state.getAttributeValue(COMPARISON_POLICY_ATTR_NAME); if (policyName != null) { - ComparisonPolicy[] policies = ComparisonPolicy.getAllInstances(); - for (ComparisonPolicy policy : policies) { + for (ComparisonPolicy policy : ComparisonPolicy.getAllInstances()) { if (policy.getName().equals(policyName)) { myComparisonPolicy = policy; break; } } } - } - private void readMode(@NotNull final Element element) { - final String modeName = element.getAttributeValue(HIGHLIGHT_MODE_ATTR_NAME); + String modeName = state.getAttributeValue(HIGHLIGHT_MODE_ATTR_NAME); if (modeName != null) { try { myHighlightMode = HighlightMode.valueOf(modeName); @@ -205,19 +241,10 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { } } - @Override - public void writeExternal(@NotNull Element element) throws WriteExternalException { - myProperties.writeExternal(element); - if (myComparisonPolicy != null) { - element.setAttribute(COMPARISON_POLICY_ATTR_NAME, myComparisonPolicy.getName()); - } - if (myHighlightMode != null) { - element.setAttribute(HIGHLIGHT_MODE_ATTR_NAME, myHighlightMode.name()); - } + public AbstractProperty.AbstractPropertyContainer getProperties() { + return myProperties; } - public AbstractProperty.AbstractPropertyContainer getProperties() { return myProperties; } - static DiffPanel createDiffPanel(DiffRequest data, Window window, @NotNull Disposable parentDisposable, FrameDiffTool tool) { DiffPanel diffPanel = null; try { @@ -236,21 +263,21 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { } } - public void setComparisonPolicy(final ComparisonPolicy p) { - myComparisonPolicy = p; - } - - @Nullable + @NotNull public ComparisonPolicy getComparisonPolicy() { return myComparisonPolicy; } - public void setHighlightMode(HighlightMode highlightMode) { - myHighlightMode = highlightMode; + public void setComparisonPolicy(@NotNull ComparisonPolicy value) { + myComparisonPolicy = value; } - @Nullable + @NotNull public HighlightMode getHighlightMode() { return myHighlightMode; } + + public void setHighlightMode(@NotNull HighlightMode highlightMode) { + myHighlightMode = highlightMode; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java index b71eeda448a1..9fbb0b2cae55 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -28,7 +28,6 @@ import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ex.MessagesEx; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -40,8 +39,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collection; -// Author: dyoma - public class FrameDiffTool implements DiffTool { public void show(DiffRequest request) { Collection hints = request.getHints(); @@ -161,27 +158,27 @@ public class FrameDiffTool implements DiffTool { // TODO remove check? private boolean checkNoDifferenceAndNotify(DiffPanel diffPanel, DiffRequest data, final Window window, final boolean showMessage) { - if (!diffPanel.hasDifferences() && !data.getHints().contains(HINT_ALLOW_NO_DIFFERENCES)) { - DiffManagerImpl manager = (DiffManagerImpl) DiffManager.getInstance(); - if (!Comparing.equal(manager.getComparisonPolicy(), ComparisonPolicy.DEFAULT)) { - ComparisonPolicy oldPolicy = manager.getComparisonPolicy(); - manager.setComparisonPolicy(ComparisonPolicy.DEFAULT); - Disposable parentDisposable = Disposer.newDisposable(); - DiffPanel maybeDiffPanel = DiffManagerImpl.createDiffPanel(data, window, parentDisposable, this); - manager.setComparisonPolicy(oldPolicy); - - boolean hasDiffs = maybeDiffPanel.hasDifferences(); - Disposer.dispose(parentDisposable); - - if (hasDiffs) return false; - } - - if (! showMessage) { - return true; - } - return !askForceOpenDiff(data); + if (diffPanel.hasDifferences() || data.getHints().contains(HINT_ALLOW_NO_DIFFERENCES)) { + return false; } - return false; + + DiffManagerImpl manager = (DiffManagerImpl)DiffManager.getInstance(); + ComparisonPolicy oldPolicy = manager.getComparisonPolicy(); + if (oldPolicy != ComparisonPolicy.DEFAULT) { + manager.setComparisonPolicy(ComparisonPolicy.DEFAULT); + Disposable parentDisposable = Disposer.newDisposable(); + DiffPanel maybeDiffPanel = DiffManagerImpl.createDiffPanel(data, window, parentDisposable, this); + manager.setComparisonPolicy(oldPolicy); + + boolean hasDiffs = maybeDiffPanel.hasDifferences(); + Disposer.dispose(parentDisposable); + + if (hasDiffs) { + return false; + } + } + + return !showMessage || !askForceOpenDiff(data); } private static boolean askForceOpenDiff(DiffRequest data) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java index fc26cf634e88..ccaa5190e587 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diff.impl.ComparisonPolicy; import com.intellij.openapi.diff.impl.ContentChangeListener; -import com.intellij.openapi.diff.impl.fragments.*; +import com.intellij.openapi.diff.impl.fragments.FragmentHighlighterImpl; +import com.intellij.openapi.diff.impl.fragments.FragmentList; +import com.intellij.openapi.diff.impl.fragments.FragmentListImpl; +import com.intellij.openapi.diff.impl.fragments.LineFragment; import com.intellij.openapi.diff.impl.processing.DiffPolicy; import com.intellij.openapi.diff.impl.processing.HighlightMode; import com.intellij.openapi.diff.impl.processing.TextCompareProcessor; @@ -58,7 +61,7 @@ public abstract class SimpleDiffPanelState implements Disposable { return editorWrapper; } - public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) { + public void setComparisonPolicy(@NotNull ComparisonPolicy comparisonPolicy) { myComparisonPolicy = comparisonPolicy; } diff --git a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java index b38c827adf9f..29f1cfaa7c6c 100644 --- a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java +++ b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,15 +16,16 @@ package com.intellij.openapi.diff.impl; import com.intellij.CommonBundle; -import com.intellij.openapi.diff.impl.string.DiffString; import com.intellij.openapi.diff.ex.DiffFragment; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.highlighting.Util; import com.intellij.openapi.diff.impl.processing.DiffCorrection; import com.intellij.openapi.diff.impl.processing.Formatting; import com.intellij.openapi.diff.impl.processing.Word; +import com.intellij.openapi.diff.impl.string.DiffString; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.diff.Diff; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; @@ -241,8 +242,7 @@ public abstract class ComparisonPolicy { if (fragment.isOneSide()) { FragmentSide side = FragmentSide.chooseSide(fragment); DiffString text = side.getText(fragment); - DiffString trimed = text.trim(); - if (trimed.isEmpty()) { + if (StringUtil.isEmptyOrSpaces(text)) { collector.add(side.createFragment(text, DiffString.EMPTY, false)); return; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java index ce6ca72ab996..8b95fbe92c8c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,7 +16,6 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.impl.ComparisonPolicy; import com.intellij.openapi.diff.impl.external.DiffManagerImpl; import com.intellij.openapi.diff.impl.fragments.LineFragment; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; @@ -87,11 +86,10 @@ public class FragmentedDiffRequestFromChange { filePath.hardRefresh(); file = filePath.getVirtualFile(); } - final PreparedFragmentedContent preparedFragmentedContent = new PreparedFragmentedContent(myProject, fragmentedContent, + return new PreparedFragmentedContent(myProject, fragmentedContent, filePath.getName(), filePath.getFileType(), change.getBeforeRevision() == null ? null : change.getBeforeRevision().getRevisionNumber(), change.getAfterRevision() == null ? null : change.getAfterRevision().getRevisionNumber(), filePath, file); - return preparedFragmentedContent; } private static class RangesCalculator { @@ -138,12 +136,8 @@ public class FragmentedDiffRequestFromChange { } } - ComparisonPolicy comparisonPolicy = DiffManagerImpl.getInstanceEx().getComparisonPolicy(); - if (comparisonPolicy == null) { - comparisonPolicy = ComparisonPolicy.DEFAULT; - } - final TextCompareProcessor processor = new TextCompareProcessor(comparisonPolicy); - final List lineFragments = processor.process(myOldDocument.getText(), myDocument.getText()); + TextCompareProcessor processor = new TextCompareProcessor(DiffManagerImpl.getInstanceEx().getComparisonPolicy()); + List lineFragments = processor.process(myOldDocument.getText(), myDocument.getText()); myRanges = new ArrayList>(lineFragments.size()); for (LineFragment lineFragment : lineFragments) { if (!lineFragment.isEqual()) { @@ -174,7 +168,7 @@ public class FragmentedDiffRequestFromChange { } } - private int correctRangeEnd(final int end, final Document document) { + private static int correctRangeEnd(final int end, final Document document) { if (end == 0) return end; return "\n".equals(document.getText(new TextRange(end - 1, end))) ? end - 1 : end; } @@ -187,7 +181,7 @@ public class FragmentedDiffRequestFromChange { return myException; } - private Document documentFromRevision(final ContentRevision cr) throws VcsException { + private static Document documentFromRevision(final ContentRevision cr) throws VcsException { final Document oldDocument = new DocumentImpl(StringUtil.convertLineSeparators(notNullContentRevision(cr)),true); // todo !!! a question how to show line separators in diff etc // todo currently document doesn't allow to put \r as separator @@ -195,7 +189,7 @@ public class FragmentedDiffRequestFromChange { return oldDocument; } - private String notNullContentRevision(final ContentRevision cr) throws VcsException { + private static String notNullContentRevision(final ContentRevision cr) throws VcsException { if (cr == null) return ""; String content = cr.getContent(); return content == null ? "" : content; diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java index 08748de5af2d..54205337eee4 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AllJarsUnderDirEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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,7 +20,6 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.roots.ui.CellAppearanceEx; import com.intellij.openapi.roots.ui.FileAppearanceService; import com.intellij.openapi.roots.ui.ModifiableCellAppearanceEx; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -55,7 +54,7 @@ public class AllJarsUnderDirEntry implements AntClasspathEntry { this(new File(osPath)); } - public void writeExternal(final Element dataElement) throws WriteExternalException { + public void writeExternal(final Element dataElement) { String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, myDir.getAbsolutePath().replace(File.separatorChar, '/')); dataElement.setAttribute(DIR, url); } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java index fb70c3728d9d..44931e324ebf 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntClasspathEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,9 +18,7 @@ package com.intellij.lang.ant.config.impl; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.roots.ui.CellAppearanceEx; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.NullableFactory; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.PathUtil; @@ -35,23 +33,25 @@ import java.util.List; public interface AntClasspathEntry { Externalizer EXTERNALIZER = new Externalizer() { @Override - public AntClasspathEntry readValue(Element dataElement) throws InvalidDataException { + public AntClasspathEntry readValue(Element dataElement) { String pathUrl = dataElement.getAttributeValue(SinglePathEntry.PATH); - if (pathUrl != null) + if (pathUrl != null) { return new SinglePathEntry(PathUtil.toPresentableUrl(pathUrl)); + } String dirUrl = dataElement.getAttributeValue(AllJarsUnderDirEntry.DIR); - if (dirUrl != null) + if (dirUrl != null) { return new AllJarsUnderDirEntry(PathUtil.toPresentableUrl(dirUrl)); - throw new InvalidDataException(); + } + throw new IllegalStateException(); } @Override - public void writeValue(Element dataElement, AntClasspathEntry entry) throws WriteExternalException { + public void writeValue(Element dataElement, AntClasspathEntry entry) { entry.writeExternal(dataElement); } }; - void writeExternal(Element dataElement) throws WriteExternalException; + void writeExternal(Element dataElement); void addFilesTo(List files); @@ -60,7 +60,7 @@ public interface AntClasspathEntry { abstract class AddEntriesFactory implements NullableFactory> { private final JComponent myParentComponent; private final FileChooserDescriptor myDescriptor; - private final Function myMapper; + private final Function myMapper; public AddEntriesFactory(final JComponent parentComponent, final FileChooserDescriptor descriptor, diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java index 12c8d141b79e..2e9405564a3d 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,8 +17,6 @@ package com.intellij.lang.ant.config.impl; import com.intellij.lang.ant.AntBundle; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.JarUtil; import com.intellij.util.config.*; import com.intellij.util.containers.Convertor; @@ -62,18 +60,18 @@ public class AntInstallation { } public static final Externalizer EXTERNALIZER = new Externalizer() { - public AntInstallation readValue(Element dataElement) throws InvalidDataException { + public AntInstallation readValue(Element dataElement) { AntInstallation antInstallation = new AntInstallation(); antInstallation.readExternal(dataElement); return antInstallation; } - public void writeValue(Element dataElement, AntInstallation antInstallation) throws WriteExternalException { + public void writeValue(Element dataElement, AntInstallation antInstallation) { antInstallation.myProperties.writeExternal(dataElement); } }; - private void readExternal(Element dataElement) throws InvalidDataException { + private void readExternal(Element dataElement) { myProperties.readExternal(dataElement); File antJar = new File(HOME_DIR.get(myProperties), PATH_TO_ANT_JAR); updateVersion(antJar); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java index f9f8d0d9eb9f..c3133da1350f 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntReference.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,6 @@ import com.intellij.execution.CantRunException; import com.intellij.lang.ant.AntBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.InvalidDataException; import com.intellij.util.config.AbstractProperty; import com.intellij.util.config.Externalizer; import org.jdom.Element; @@ -35,11 +34,13 @@ public abstract class AntReference { @NonNls private static final String BUNDLED_ANT_ATTR = "bundledAnt"; public static final Externalizer EXTERNALIZER = new Externalizer() { - public AntReference readValue(Element dataElement) throws InvalidDataException { + public AntReference readValue(Element dataElement) { if (Boolean.valueOf(dataElement.getAttributeValue(PROJECT_DEFAULT_ATTR)).booleanValue()) return PROJECT_DEFAULT; if (Boolean.valueOf(dataElement.getAttributeValue(BUNDLED_ANT_ATTR)).booleanValue()) return BUNDLED_ANT; String name = dataElement.getAttributeValue(NAME_ATTR); - if (name == null) throw new InvalidDataException(); + if (name == null) { + throw new IllegalStateException("no name"); + } return new MissingAntReference(name); } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java index 43655b0463b4..d0166ffef749 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/GlobalAntConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,8 +31,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.config.*; @@ -102,24 +100,13 @@ public class GlobalAntConfiguration implements PersistentStateComponent @Override public Element getState() { Element element = new Element("state"); - try { - myProperties.writeExternal(element); - } - catch (WriteExternalException e) { - LOG.error(e); - return null; - } + myProperties.writeExternal(element); return element; } @Override public void loadState(Element state) { - try { - myProperties.readExternal(state); - } - catch (InvalidDataException e) { - LOG.error(e); - } + myProperties.readExternal(state); } public static GlobalAntConfiguration getInstance() { diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java index 76581fd86f0c..ac982d676255 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/SinglePathEntry.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,8 +18,6 @@ package com.intellij.lang.ant.config.impl; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.roots.ui.CellAppearanceEx; import com.intellij.openapi.roots.ui.FileAppearanceService; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -51,12 +49,12 @@ public class SinglePathEntry implements AntClasspathEntry { this(new File(osPath)); } - public void readExternal(final Element element) throws InvalidDataException { + public void readExternal(final Element element) { String value = element.getAttributeValue(PATH); myFile = new File(PathUtil.toPresentableUrl(value)); } - public void writeExternal(final Element element) throws WriteExternalException { + public void writeExternal(final Element element) { String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, myFile.getAbsolutePath().replace(File.separatorChar, '/')); element.setAttribute(PATH, url); } From d0479adb516f2b4dd179e302c15fa6e68500daf1 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 12:29:41 +0100 Subject: [PATCH 145/231] move TestListener extension point registration to correct place --- .../src/META-INF/PlatformExtensionPoints.xml | 1 + .../sm/runner/ui/SMTRunnerNotificationsHandler.java | 3 +-- resources/src/META-INF/IdeaPlugin.xml | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index e8ce7ae50d9c..a16d0325abbf 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -241,5 +241,6 @@ + diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java index b8e276354945..7b4a539a4721 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerNotificationsHandler.java @@ -99,8 +99,7 @@ public class SMTRunnerNotificationsHandler extends SMTRunnerEventsAdapter { type = null; } - // todo: need to provide default implementation before notifying test status listeners to avoid IAE - //TestStatusListener.notifySuiteFinished(testsRoot, myConsoleProperties.getProject()); + TestStatusListener.notifySuiteFinished(testsRoot, myConsoleProperties.getProject()); if (msg != null) { notify(msg, type, testsRoot); diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 333d87167237..ded75cc64893 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -273,8 +273,6 @@ - - From 2e4f8a79e2b66d7423b435c3bfb78b3fb3700019 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 23 Feb 2015 13:20:28 +0100 Subject: [PATCH 146/231] attr made fixed --- .../lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index 8b6843dab3ad..66f5de4179ad 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -46,7 +46,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubUpdatingIndex"); // todo remove once we don't need this for stub-ast mismatch debug info - private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 2, false); + private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 2, true); public static final ID INDEX_ID = ID.create("Stubs"); From 7b6776b86661d0333a3af049b09739a25f2cce1e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 13:03:19 +0100 Subject: [PATCH 147/231] generate setter: correct annotation place (IDEA-136851) --- .../generation/GenerateMembersUtil.java | 15 ++++++++- .../GenerateGetterSetterTest.groovy | 32 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java index 9817ce5e631d..3dca018ab61a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersUtil.java @@ -664,7 +664,20 @@ public class GenerateMembersUtil { } } result = (PsiMethod)CodeStyleManager.getInstance(project).reformat(result); - PropertyUtil.annotateWithNullableStuff(field, result); + + PsiModifierListOwner listOwner = null; + if (templatesManager instanceof GetterTemplatesManager) { + listOwner = result; + } + else { + final PsiParameter[] parameters = result.getParameterList().getParameters(); + if (parameters.length == 1) { + listOwner = parameters[0]; + } + } + if (listOwner != null) { + PropertyUtil.annotateWithNullableStuff(field, listOwner); + } return generatePrototype(field, result); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy index 50206caa0053..b27540c6a50d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy @@ -122,6 +122,38 @@ class Foo { ''' } + public void "test nullable stuff"() { + myFixture.addClass("package org.jetbrains.annotations;\n" + + "public @interface NotNull {}") + myFixture.configureByText 'a.java', ''' +class Foo { + @org.jetbrains.annotations.NotNull + private String myName; + + +} +''' + generateGetter() + generateSetter() + myFixture.checkResult '''import org.jetbrains.annotations.NotNull; + +class Foo { + @org.jetbrains.annotations.NotNull + private String myName; + + public void setMyName(@NotNull String myName) { + this.myName = myName; + } + + @NotNull + public String getMyName() { + + return myName; + } +} +''' + } + private void generateGetter() { WriteCommandAction.runWriteCommandAction(getProject(), { new GenerateGetterHandler() { From f0c0ee6a4809a9500a130dc050f0241a2b40aba2 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 13:17:02 +0100 Subject: [PATCH 148/231] show error if test runner doesn't provide description (IDEA-136817) --- .../src/com/intellij/junit4/JUnit4IdeaTestRunner.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java index 3fba1a3d9b7a..dae5c95b0241 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java @@ -41,6 +41,10 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner { final Runner testRunner = request.getRunner(); try { Description description = testRunner.getDescription(); + if (description == null) { + System.err.println("Nothing found to run. Runner " + testRunner.getClass().getName() + " provides no description."); + return -1; + } if (request instanceof ClassRequest) { description = getSuiteMethodDescription(request, description); } From 220b683fa2acc56bd60e723faffca46626e4772b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Feb 2015 13:34:41 +0100 Subject: [PATCH 149/231] platform: JarLoader prevented from using ZIP file cache First, this effectively doesn't change the behavior - as ZipFileCache was effectively disabled by a (somewhat inconvenient) condition in it. Next, this allows to drop the condition while still preventing it from loading at bootstrap. --- .../ide/BootstrapClassLoaderUtil.java | 2 +- .../openapi/util/io/ZipFileCache.java | 35 +++++-------------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java index 29a8905a45b9..3bd742189c07 100644 --- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java @@ -62,7 +62,7 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { UrlClassLoader.Builder builder = UrlClassLoader.build() .urls(filterClassPath(classpath)) - .allowLock() + .allowLock(false) .usePersistentClasspathIndexForLocalClassDirectories() .useCache(); if (Boolean.valueOf(System.getProperty(PROPERTY_ALLOW_BOOTSTRAP_RESOURCES, "true"))) { diff --git a/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java b/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java index bf98c0f63b6d..65a7ee3988a7 100644 --- a/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java +++ b/platform/util/src/com/intellij/openapi/util/io/ZipFileCache.java @@ -68,9 +68,6 @@ public class ZipFileCache { } } - private static final boolean ourEnabled = - ZipFileCache.class.getClassLoader().getResource("com/intellij/openapi/application/Application.class") != null; - private static final Object ourLock = new Object(); private static final Map ourPathCache = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY); private static final Map ourFileCache = ContainerUtil.newHashMap(); @@ -79,29 +76,20 @@ public class ZipFileCache { private static final ScheduledThreadPoolExecutor ourExecutor; static { - if (ourEnabled) { - ourExecutor = ConcurrencyUtil.newSingleScheduledThreadExecutor("ZipFileCache Dispose", Thread.MIN_PRIORITY); - ourExecutor.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - List toClose = getFilesToClose(0, System.currentTimeMillis() - TIMEOUT); - if (toClose != null) { - close(toClose); - } + ourExecutor = ConcurrencyUtil.newSingleScheduledThreadExecutor("ZipFileCache Dispose", Thread.MIN_PRIORITY); + ourExecutor.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + List toClose = getFilesToClose(0, System.currentTimeMillis() - TIMEOUT); + if (toClose != null) { + close(toClose); } - }, PERIOD, PERIOD, TimeUnit.MILLISECONDS); - } - else { - ourExecutor = null; - } + } + }, PERIOD, PERIOD, TimeUnit.MILLISECONDS); } @NotNull public static ZipFile acquire(@NotNull String path) throws IOException { - if (!ourEnabled) { - return new ZipFile(path); - } - path = FileUtil.toCanonicalPath(path); synchronized (ourLock) { @@ -178,11 +166,6 @@ public class ZipFileCache { } public static void release(@NotNull ZipFile file) { - if (!ourEnabled) { - close(file); - return; - } - synchronized (ourLock) { CacheRecord record = ourFileCache.get(file); if (record != null) { From fc465900b69414c44f1724761ed39010b1ad0b8f Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Feb 2015 13:35:16 +0100 Subject: [PATCH 150/231] Cleanup (formatting; names; unneeded condition) --- .../src/com/intellij/util/lang/JarLoader.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/util/src/com/intellij/util/lang/JarLoader.java b/platform/util/src/com/intellij/util/lang/JarLoader.java index 9c1fa395e6af..4a040e53ef88 100644 --- a/platform/util/src/com/intellij/util/lang/JarLoader.java +++ b/platform/util/src/com/intellij/util/lang/JarLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -64,7 +64,7 @@ class JarLoader extends Loader { if (myCanLockJar) { ZipFileCache.release(zipFile); } - else if (zipFile != null) { + else { zipFile.close(); } } @@ -72,21 +72,21 @@ class JarLoader extends Loader { @NotNull @Override public ClasspathCache.LoaderData buildData() throws IOException { - ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData(); ZipFile zipFile = acquireZipFile(); try { + ClasspathCache.LoaderData loaderData = new ClasspathCache.LoaderData(); Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()) { - ZipEntry zipEntry = entries.nextElement(); - String name = zipEntry.getName(); + ZipEntry entry = entries.nextElement(); + String name = entry.getName(); loaderData.addResourceEntry(name); loaderData.addNameEntry(name); } + return loaderData; } finally { releaseZipFile(zipFile); } - return loaderData; } @Override @@ -99,15 +99,15 @@ class JarLoader extends Loader { } try { - ZipFile file = acquireZipFile(); + ZipFile zipFile = acquireZipFile(); try { - ZipEntry entry = file.getEntry(name); + ZipEntry entry = zipFile.getEntry(name); if (entry != null) { - return MemoryResource.load(getBaseURL(), file, entry); + return MemoryResource.load(getBaseURL(), zipFile, entry); } } finally { - releaseZipFile(file); + releaseZipFile(zipFile); } } catch (Exception e) { From d9fcd582b143f15f05a939408a4a654307400611 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Feb 2015 13:35:23 +0100 Subject: [PATCH 151/231] rollback @2x icons --- .../icons/src/ide/shadow/popup/bottom-left@2x.png | Bin 356 -> 0 bytes .../src/ide/shadow/popup/bottom-right@2x.png | Bin 347 -> 0 bytes platform/icons/src/ide/shadow/popup/bottom@2x.png | Bin 134 -> 0 bytes platform/icons/src/ide/shadow/popup/left@2x.png | Bin 122 -> 0 bytes platform/icons/src/ide/shadow/popup/right@2x.png | Bin 122 -> 0 bytes .../icons/src/ide/shadow/popup/top-left@2x.png | Bin 242 -> 0 bytes .../icons/src/ide/shadow/popup/top-right@2x.png | Bin 242 -> 0 bytes platform/icons/src/ide/shadow/popup/top@2x.png | Bin 110 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 platform/icons/src/ide/shadow/popup/bottom-left@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/bottom-right@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/bottom@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/left@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/right@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/top-left@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/top-right@2x.png delete mode 100644 platform/icons/src/ide/shadow/popup/top@2x.png diff --git a/platform/icons/src/ide/shadow/popup/bottom-left@2x.png b/platform/icons/src/ide/shadow/popup/bottom-left@2x.png deleted file mode 100644 index 17b7f4d2682eef698c2dbe8be2715bf402228c7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 356 zcmV-q0h|7bP)74PVwAMk~)4a_KT7K^B$fwty&hiAOu1D^qX z9Xbe%FoSuuY2Wi6j&O-vRr-jhfEPTtz^wX@)wZp2OS80XyAyDui!}ZmZQBK1 zPDMAqqiS3F(>M%hYu$bVBUPFALRYb_o3E+rM!>cng>h~Bp|;Wl3s};AmNehBA-iryJ-c-TKYr^LnObK+*Rs=bK@*_=*xHqjO-h~4I{9vF42(y0000 zOHaZ;6o%naE=80Y43WY@L&7aA3|>$cLI?(2xY8H`ZX_W_|Nk%Wt9eVBrem~h+T_`t zew{gUrk3^pCodDZmbQ4}iX&MoVc>&|q$dqI-ZyY2x6(~@;9cqi)7!(GOl2q?sYe5y zKPsRU8thiwU~lA0J`Fyod6O4;B=AC-aw=s$_7nIXdNIzHnzcO3f?Lv;bE(P^y|pch zRZv|$%GV;c*DIW=QeHsEy6*skBd0}d&B&fm4D)g?%>g*uUW0rp75mKdRE-Ne2yKFenWiU-#lvz=U tASW&?$zbQ%Vz5m+dX?-1GQo*PpKtrNBkwS|Y4iX9002ovPDHLkV1j5^k);3t diff --git a/platform/icons/src/ide/shadow/popup/bottom@2x.png b/platform/icons/src/ide/shadow/popup/bottom@2x.png deleted file mode 100644 index cb4fcb9fbb95e5d1c563a4fee4a4247edcea8b91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrA!VDza|7cbMDY*cj5LY0L2W;2K&jLzwl?3?( zr>BOwnW{_E)O!VDxIsIL4Aq(lRJLR^6~CJ_E)O!VDxIsIL4Aq(lRJLR^6~CJG;%8@`6Y(n+D8%dO;uyjqo173*<_k0~hT&95N)yOr22WQ%mvv4FO#m(W6tDmQ diff --git a/platform/icons/src/ide/shadow/popup/top-left@2x.png b/platform/icons/src/ide/shadow/popup/top-left@2x.png deleted file mode 100644 index 3a6ca6530854f7ebf49c0aaa7056e4693b03dd95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242 zcmVPwx&W*E>rlRmLP>)ydvMfG24)w>oSr)pG zLjl^O6=*h>P(dFISg0MXDw+Yq4MP~i6lO5z_ZMtJJqAXcQvu(hc)f}tIei&wg0Gt8 zwbroXd^DJ|+5i>|9XTHj7JQpjTfqS?DM8J)PhbNlxbwi^Pz)Njc?)NFqy}sLBYEEy sUMaznL21k$ZtzYGTBo8k<{1lq0Lu*rNn`vHp8x;=07*qoM6N<$g0c}@WB>pF diff --git a/platform/icons/src/ide/shadow/popup/top-right@2x.png b/platform/icons/src/ide/shadow/popup/top-right@2x.png deleted file mode 100644 index 567bd08fbc83ae7fcc17b681b334ebfe8069eb54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 242 zcmV9U6a>(iG*)Xh;;Sks2uc^aaG`>36!HJR$+<8}&^Ars&`st(5~Y;VKU$vP*REh8 z0YjBV2A)3T(1Q$87D~KnzTXTA{--d35jYm=)`fKq;}yslHZi+Pc*!Z8*I73OrTP|D z9AC!naO7ZDIdFg-EMUm4HYRw6J*;8O+qO;P%7GgkVZ&YXm^~$UhZA=#_|~7>4F;cZ s;hu8_)0p53u2Ax6Tx{^c3;OH$2GwE*k^i4cxBvhE07*qoM6N<$f{52-7XSbN diff --git a/platform/icons/src/ide/shadow/popup/top@2x.png b/platform/icons/src/ide/shadow/popup/top@2x.png deleted file mode 100644 index 495941809e23f40ae2667513dafcd6079e30a478..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr7#0(^jw(VUBq<8{+LR^6~9GJc|p9bWxlmz(& vGqLfBGq_j10`hr1T^vI=WRnvU3K<+3m}W3s)D?Il0Mg~@>gTe~DWM4fzlRiE From 793394479cd721e0493f01ac3730a037b7afd939 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Feb 2015 13:35:51 +0100 Subject: [PATCH 152/231] rollback @2x icons --- platform/icons/src/ide/shadow/bottom-left@2x.png | Bin 1510 -> 0 bytes .../icons/src/ide/shadow/bottom-right@2x.png | Bin 1525 -> 0 bytes platform/icons/src/ide/shadow/bottom@2x.png | Bin 313 -> 0 bytes platform/icons/src/ide/shadow/left@2x.png | Bin 233 -> 0 bytes platform/icons/src/ide/shadow/right@2x.png | Bin 245 -> 0 bytes platform/icons/src/ide/shadow/top-left@2x.png | Bin 1055 -> 0 bytes platform/icons/src/ide/shadow/top-right@2x.png | Bin 1169 -> 0 bytes platform/icons/src/ide/shadow/top@2x.png | Bin 175 -> 0 bytes 8 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 platform/icons/src/ide/shadow/bottom-left@2x.png delete mode 100644 platform/icons/src/ide/shadow/bottom-right@2x.png delete mode 100644 platform/icons/src/ide/shadow/bottom@2x.png delete mode 100644 platform/icons/src/ide/shadow/left@2x.png delete mode 100644 platform/icons/src/ide/shadow/right@2x.png delete mode 100644 platform/icons/src/ide/shadow/top-left@2x.png delete mode 100644 platform/icons/src/ide/shadow/top-right@2x.png delete mode 100644 platform/icons/src/ide/shadow/top@2x.png diff --git a/platform/icons/src/ide/shadow/bottom-left@2x.png b/platform/icons/src/ide/shadow/bottom-left@2x.png deleted file mode 100644 index 10e5d1c9c5f60e1ed3d5fde61550594f0a8da45e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1510 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT3?e@WZDU|y3=Z%KasB`QKTu>8P%#AVH@#{F z8dq2n ztEX>ZXk=_+YG!U>X=QC=YiIA^=;Z9;>gMj@>E-R?>*pU37!({58WtWA85JE98yBCD zn3SB7nwFlCnU$TBo0ng3_L!s-0|WC#PZ!6Kh}NZH;Yr%&0?v|m|LeW9l>KbjdS~jq zT+L1PTX?w>90F7vCoRzk+?1l3WBsMT;*a#czaQ8RPtds?)^fP7KOyB7&+W1+_pJ>K zT&HT>?)tCnH7!N^4bxASwmdWWt}L@nF(opZZ=3@&H$Gy{Utny0QcZ@>b@Ps zOJum}8JrD`%!@XtfBju;U~<&KBg`jHCjXFvhb(h>i;`14Q02KFKMii$w>2J<2`_S* zDc%0BhI<+Nxd~e4oS(1vC$4B*So|pL#lwIfyb@Z85sREoy}9|3&qv?);f4F{RPNULq4H5w^5 zJ5roGMK}Z*j?bRVo48BNWm3Tg7tcuv2dDlN+T3xp(J|5|IP`?-iD^%5=I_#+@FZ!o zWS{~oXV9!O3#wx}D;p-XOmkRZYnPZYrF&;|YSp4Zmf%GWPmOQS;`Y(=-{>^S#zsSk zb^F94PtvNJ^VXeW3-Q9# zLfy_Z={whS5+?|;Wy+p*^V~Z3^vwH{T9!D8v<8cuJF9j0@xMaFYxRMF&)--cRcMUT ze!L{L<EU zo6?rXT`Q&pHdq~eduC~VRm3XUq`KIUV9s+sipk7h=MA>%^zzYsqVwrkHad z(w7>sGQF9B=L|>^j6*tRN^M71P@)yUUqd?7hKt zp0_@HO=TZ0?6mA#e@e}z**tu=#r(DstFygj4KhvflEn>iKSPZ8g0H82;VEjijK7h> zx9~>xgMUBX^5{qGso6iHJHB@BnK!>aJiYX4=6pH(pCyxaUEIO*bn6c3h0XstE9)Pa zo~iwFU3hz84ddrmJFm~%SNFeL_`Ko&N1tDP>MYq_YL(x&zv{I9ls`}Yz1OQ<`da#| h{f>vdyZ7z=Y5(p){$3S~6@vd$@?2>^W82M7QF diff --git a/platform/icons/src/ide/shadow/bottom-right@2x.png b/platform/icons/src/ide/shadow/bottom-right@2x.png deleted file mode 100644 index 771dfef1db73f41b2ea7be0e40733473558d8f22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1525 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT3?e@WZDU|y3=Z%KasB`QKTu>8P%#AVH@#{F z8dq2n ztEX>ZXk=_+YG!U>X=QC=YiIA^=;Z9;>gMj@>E-R?>*pU37!({58WtWA85JE98yBCD zn3SB7nwFlCnU$TBo0ng3_L!s-0|WB|PZ!6Kh{JQIJ5GCS!Q*`J<(&L;M&IiN|LJ&K zoHDs;>Xzz>Avp&bJe*!#cz=EW>z(sn|E#H6yLFyU^-UcEhK_o>2Ej>7I5;(by)XQ) zJR@Vx4#qdXd4=feSg0 z8Xj2BU<%r>zexEjC(oo7MZ-tE>-=weC?G9jsI)4oV~60c8%fKz1b)wVeOp%i z-S=iNg{E*_JbwK`LiZ+}Z#`}9w5!B)d7HDA9*C^~v5OgVr0MuYY5 z%|G|=P1}>Q`oxYaQ=8a!{Hfd$cYK=v&7{XB?qxUYH@#TnVWz~w=YBP7fy&}3&!@!C zHIaJpQKni$VpmXTNl$p2yp!0Yu)LRynSa)$NZ!&gvL zRTU?bHm-VgBYNAdbIu{}B_qABJFK16p1M1Sv1#HW6`sdS9%g->(;%`rq9{1U@9BqU zD^EYZ`+94_Rf7}U`Z;CqpBnT}n!jjEqE7VgnAM*a|71Ag=W@{?GEZ;LnYN{ip4{y( z{jlZSyWK9aTQ^-;bth6Q^V=!`Mv-uZ&rHd#=?DET=az2cyYAa4v-p8>zKqATIeWNU zPR&15AZ{I}qb3uyPa!^IWzF4*aSugpkKX$KrQ+QlO}(G1vVI#%>|3?<``W{gUI?yt z7P#BC;LPJEOJq;q;aMlJw=CJ+)cRV%EV1p&cZ=+mJsVJNr9Az)$`s}AXTQ%g7Z;i< zbwW0BF8}kN&!o<(Y%W#KGCwyXJU{I3gj?s0UB2ttteQ7_&icIu>565RCOYSyJ}un0 zpzP7yyV3r{O#w>_e5sq~`WS{h5vBAz3lA#{wt2!eB4&6^Um?*AB#G+#XrvW zvU+c(q4}MkM|OT$_cUYw_5aC*br1XM&d)M8*z^Bf^%ePF&(5~q)7zI_Q8Ksg!4>1* z#%)XN7jD1)G2_GG-uT3OdJm7Q|9`Q#JN}*hzq*%u{;_XgAT+0T-<)Tla?8`z&t;uc GLK6T(2Qp3o diff --git a/platform/icons/src/ide/shadow/bottom@2x.png b/platform/icons/src/ide/shadow/bottom@2x.png deleted file mode 100644 index ad69deefa9b67e4226fa9f50c71ab7ecb5087476..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^j6iJ2!3-pIHX4fosonse5LX~Qc)+W6;~zlR=$8cf z1v9ebWo4(OB*te%gogzBdAYkd*uEal|5uGfMp1{=f-zVoxkB`8K!)F*$6`eUZtYC=|jXQDR#E}C_c$YLXF!YNt Uu|L{l_zV;Pp00i_>zopr0AS56tpET3 diff --git a/platform/icons/src/ide/shadow/left@2x.png b/platform/icons/src/ide/shadow/left@2x.png deleted file mode 100644 index 78c558d74d75db1d5863832ed29a8a0275d9173d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG>!3-pmlb?qHsk8u}5LX~g2T+hRf$rIH}O zU?xUp7FITP4lZt9egPp7aY<=81tm329epD+3tI;lcW=LCeGlb;ss%h<978x{lT-ej eKX9Z&o`FH7l2Q5mKAU)ugFRjST-G@yGywqWC>*^2 diff --git a/platform/icons/src/ide/shadow/right@2x.png b/platform/icons/src/ide/shadow/right@2x.png deleted file mode 100644 index d2afef8fd36d2cdc3f2c6a4a15d6bd6b587eddba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^%0SG>!3-pmlb?qHsk8u}5LX~g2T+hRf$rIH}O zU?x9zZwFfo7bATgO*Lf&Gigb25g`G7UT!W9b~aWPW;sTu%=}$I)iRzgjv*Yf$tfwn q&i|S|apGrnWeJYj1Q%9*NfE~4N>*iMN$oQr$9uZ^xvXAt@y-BP%Dbps1v*qN=8@p{b>cH9a++?`&VTvH@#Mx0e$gHM3+%oNsAo6|98@`Gv&2fRTk^X;S4ZshisC25 zn=7~%JO0}367`KGXGUa1bCXN5L5Js6j#o>6-q4gi(6wgqE`R5aCYdX0yYJuTZ(-HA z6Z%zamZ?-pcbCT>bcNwu|@UP<3TIm?=zIB)JJ|ETKm2AZ?Z^oGB zUlM9CedWLW-kswu6LtyAK0RkuX0bu~>bW|*XBAvq(P?Jg`g7^w<1XKHk~f^6ojA>J zc3|I3(lANz7hlfAT_Po`+qy)`E6wSQTEE|1hvoEhn;KE*~OVzskLe8|>_-~UeJ zwtlcwi{~g7R=ATK?CHCuZ^ro=!>~(H0WU30XPvQF{zgL6ttsv1m8PV%dz}Qfteb!N z%^JyVyv|$HN@d=EpDT0j{GE$k0#|j?PGorg%Fg~(+OcfqJ@;^ty8j>Ir9VuN)>w5` zAahQWh}_Qgt0M3F&-wM~(yTR3%hLPh4V1S<)?}BiPx4R+wf>V>ta8bpf6LA#{JHAt@y-BP%Dbps1v*qN=8@p{b>?rw0T4JWd zrRsV+(QjVTI-3d>C$$bM zOr77A|2$`2x4grSRc#K}+3QXxwKwyXs7?FAs$%fRf6`aRg4hX$pR%sJQL++9Uo`21 znoQKg#Tv|ugr5yF4oXsrT((#lD6PO z{m@klS4;}AFnZi-ee>xw&fEz>?j46p5+pR;C0G>=Hc0S=hPE#_d@#_1Z$ZmsuSJ&_ zJ6^geurM?D_W4`z653yb4I1uKa&8$;DZH>-&?Yie~lK2#2v=6LlRUo(H~g&lLg&xyL9(Ubf|s+RX;thRwP_5DEWULn?=;L7s?3tK(A^Sr>Bc6_xhvJ|Ct67O z?(MccY`gNt_RnQ;>%FgbH2D7dXEF6s{i_gLSvvV>P}&k9pV#S0 kj<4o#K9Od1$)ffj|J9X|8$WJu6#^A3p00i_>zopr0E6O)EC2ui diff --git a/platform/icons/src/ide/shadow/top@2x.png b/platform/icons/src/ide/shadow/top@2x.png deleted file mode 100644 index a893e2458eec64fb9112636e507b4549b1388d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{H!3-p;FD#!7q|5?*LR^6~8DM)^MiEe(P)U$q zFe3{y6B|1R7dJ1zfRKo|q_iAI)ah$LSusx+#}E$L Date: Mon, 23 Feb 2015 14:13:42 +0100 Subject: [PATCH 153/231] disable shadows for HiDPI configurations for awhile --- .../intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index 7717de4a616d..28af087d7816 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -41,6 +41,7 @@ import com.intellij.openapi.wm.impl.IdeGlassPaneEx; import com.intellij.ui.FocusTrackback; import com.intellij.ui.ScreenUtil; import com.intellij.ui.components.JBLayeredPane; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -591,7 +592,7 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc } private void createShadow() { - if (!UISettings.isRemoteDesktopConnected()) { + if (!UISettings.isRemoteDesktopConnected() && !JBUI.isHiDPI()) { shadow = ShadowBorderPainter.createShadow(this, getWidth(), getHeight()); } } From 3ed0fef7fe31a86600482f70504ed705c2092552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Mon, 23 Feb 2015 15:00:29 +0100 Subject: [PATCH 154/231] PatternPackageReferenceSet.processSubPackages: restore recursive invocation (IDEA-COMMUNITY-CR-1557) --- .../impl/providers/PatternPackageReferenceSet.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java index ef1085f32bb6..c93b33068c1b 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PatternPackageReferenceSet.java @@ -19,7 +19,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPackage; import com.intellij.util.PatternUtil; import com.intellij.util.Processor; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -62,6 +61,9 @@ public class PatternPackageReferenceSet extends PackageReferenceSet { protected static boolean processSubPackages(final PsiPackage pkg, final Processor processor) { if (!processor.process(pkg)) return false; - return ContainerUtil.process(pkg.getSubPackages(), processor); + for (final PsiPackage aPackage : pkg.getSubPackages()) { + if (!processSubPackages(aPackage, processor)) return false; + } + return true; } } From 93679fde4678fed47e4061a6ef5fabc31cb497d1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 23 Feb 2015 15:34:16 +0100 Subject: [PATCH 155/231] platform: class path fixes and cleanups - no more duplicates in class path - correct order of entries copied from app class loader hierarchy - dysfunctional case of Ant class loaders dropped --- .../ide/BootstrapClassLoaderUtil.java | 87 +++++++------------ 1 file changed, 32 insertions(+), 55 deletions(-) diff --git a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java index 3bd742189c07..6e313990e112 100644 --- a/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java +++ b/platform/bootstrap/src/com/intellij/ide/BootstrapClassLoaderUtil.java @@ -20,7 +20,6 @@ import com.intellij.idea.Main; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.lang.UrlClassLoader; import com.intellij.util.text.StringTokenizer; @@ -28,13 +27,10 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.regex.Pattern; /** @@ -55,13 +51,13 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { public static ClassLoader initClassLoader(boolean updatePlugins) throws MalformedURLException { PathManager.loadProperties(); - List classpath = new ArrayList(); + Collection classpath = new LinkedHashSet(); addParentClasspath(classpath); addIDEALibraries(classpath); addAdditionalClassPath(classpath); UrlClassLoader.Builder builder = UrlClassLoader.build() - .urls(filterClassPath(classpath)) + .urls(filterClassPath(new ArrayList(classpath))) .allowLock(false) .usePersistentClasspathIndexForLocalClassDirectories() .useCache(); @@ -85,68 +81,35 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { return newClassLoader; } - private static List filterClassPath(List classpathElements) { - String ignoreProperty = System.getProperty(PROPERTY_IGNORE_CLASSPATH); - if (ignoreProperty != null) { - Pattern pattern = Pattern.compile(ignoreProperty); - for (Iterator i = classpathElements.iterator(); i.hasNext(); ) { - String url = i.next().toExternalForm(); - if (pattern.matcher(url).matches()) { - i.remove(); - } - } - } - return classpathElements; - } - - private static void addParentClasspath(List classpathElements) throws MalformedURLException { + private static void addParentClasspath(Collection classpath) throws MalformedURLException { + List loaders = new ArrayList(2); for (ClassLoader loader = BootstrapClassLoaderUtil.class.getClassLoader(); loader != null; loader = loader.getParent()) { if (loader instanceof URLClassLoader) { - ContainerUtil.addAll(classpathElements, ((URLClassLoader)loader).getURLs()); + loaders.add(0, (URLClassLoader)loader); } else { - String loaderName = loader.getClass().getName(); - try { - Class antClassLoaderClass = Class.forName("org.apache.tools.ant.AntClassLoader"); - if (antClassLoaderClass.isInstance(loader) || - "org.apache.tools.ant.AntClassLoader".equals(loaderName) || - "org.apache.tools.ant.loader.AntClassLoader2".equals(loaderName)) { - String classpath = (String)antClassLoaderClass - .getDeclaredMethod("getClasspath", ArrayUtil.EMPTY_CLASS_ARRAY) - .invoke(loader, ArrayUtil.EMPTY_OBJECT_ARRAY); - StringTokenizer tokenizer = new StringTokenizer(classpath, File.separator, false); - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken(); - classpathElements.add(new File(token).toURI().toURL()); - } - } - else { - getLogger().warn("Unknown class loader: " + loaderName); - } - } - catch (ClassCastException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (ClassNotFoundException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (NoSuchMethodException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (IllegalAccessException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } - catch (InvocationTargetException e) { getLogger().warn("Unknown class loader '" + loaderName + "'", e); } + getLogger().warn("Unknown class loader: " + loader.getClass().getName()); } } + for (URLClassLoader loader : loaders) { + ContainerUtil.addAll(classpath, loader.getURLs()); + } } - private static void addIDEALibraries(List classpathElements) throws MalformedURLException { + private static void addIDEALibraries(Collection classpath) throws MalformedURLException { Class aClass = BootstrapClassLoaderUtil.class; String selfRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class"); assert selfRoot != null; URL selfRootUrl = new File(selfRoot).getAbsoluteFile().toURI().toURL(); - classpathElements.add(selfRootUrl); + classpath.add(selfRootUrl); File libFolder = new File(PathManager.getLibPath()); - addLibraries(classpathElements, libFolder, selfRootUrl); - addLibraries(classpathElements, new File(libFolder, "ext"), selfRootUrl); - addLibraries(classpathElements, new File(libFolder, "ant/lib"), selfRootUrl); + addLibraries(classpath, libFolder, selfRootUrl); + addLibraries(classpath, new File(libFolder, "ext"), selfRootUrl); + addLibraries(classpath, new File(libFolder, "ant/lib"), selfRootUrl); } - private static void addLibraries(List classPath, File fromDir, URL selfRootUrl) throws MalformedURLException { + private static void addLibraries(Collection classPath, File fromDir, URL selfRootUrl) throws MalformedURLException { File[] files = fromDir.listFiles(); if (files == null) return; @@ -160,16 +123,30 @@ public class BootstrapClassLoaderUtil extends ClassUtilCore { } } - private static void addAdditionalClassPath(List classPath) { + private static void addAdditionalClassPath(Collection classpath) { try { StringTokenizer tokenizer = new StringTokenizer(System.getProperty(PROPERTY_ADDITIONAL_CLASSPATH, ""), File.pathSeparator, false); while (tokenizer.hasMoreTokens()) { String pathItem = tokenizer.nextToken(); - classPath.add(new File(pathItem).toURI().toURL()); + classpath.add(new File(pathItem).toURI().toURL()); } } catch (MalformedURLException e) { getLogger().error(e); } } + + private static List filterClassPath(List classpath) { + String ignoreProperty = System.getProperty(PROPERTY_IGNORE_CLASSPATH); + if (ignoreProperty != null) { + Pattern pattern = Pattern.compile(ignoreProperty); + for (Iterator i = classpath.iterator(); i.hasNext(); ) { + String url = i.next().toExternalForm(); + if (pattern.matcher(url).matches()) { + i.remove(); + } + } + } + return classpath; + } } From d02256cb8c4a97fac607ebc6341ed58ff86bd13a Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 23 Feb 2015 16:22:05 +0100 Subject: [PATCH 156/231] remove logging --- .../src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 8e9ca5a93e52..14b5be48ce43 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -80,7 +80,7 @@ public class DarculaLaf extends BasicLookAndFeel { @SuppressWarnings("UnusedParameters") private static void log(Exception e) { // everything is gonna be alright - e.printStackTrace(); +// e.printStackTrace(); } @Override From 784d2fe868225c72bf814147b92e577125733694 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 21 Feb 2015 12:22:58 +0100 Subject: [PATCH 157/231] SSR: fix within predicate for different languages --- .../impl/matcher/compiler/PatternCompiler.java | 3 ++- .../impl/matcher/predicates/WithinPredicate.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java index 07808d33c003..6a20da7294c9 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java @@ -466,7 +466,8 @@ public class PatternCompiler { ); if (!StringUtil.isEmptyOrSpaces(constraint.getWithinConstraint())) { - MatchPredicate predicate = new WithinPredicate(Configuration.CONTEXT_VAR_NAME, constraint.getWithinConstraint(), project); + MatchPredicate predicate = + new WithinPredicate(Configuration.CONTEXT_VAR_NAME, constraint.getWithinConstraint(), options.getFileType(), project); if (constraint.isInvertWithinConstraint()) { predicate = new NotPredicate(predicate); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java index 3904eb397bce..c891cb1c1ec5 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java @@ -1,5 +1,6 @@ package com.intellij.structuralsearch.impl.matcher.predicates; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; @@ -16,11 +17,12 @@ public class WithinPredicate extends AbstractStringBasedPredicate { private final MatchOptions myMatchOptions; private Matcher matcher; - public WithinPredicate(String name, String within, Project project) { + public WithinPredicate(String name, String within, FileType fileType, Project project) { super(name, within); myMatchOptions = new MatchOptions(); myMatchOptions.setLooseMatching(true); + myMatchOptions.setFileType(fileType); final String unquoted = StringUtil.stripQuotesAroundValue(within); if (!unquoted.equals(within)) { myMatchOptions.setSearchPattern(unquoted); From 11336b7a7bab9aac955a7d0ffabbdacae16f824d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sun, 22 Feb 2015 13:12:18 +0100 Subject: [PATCH 158/231] SSR: initialize file type lazily --- .../com/intellij/structuralsearch/MatchOptions.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java index 2d67883ad6e3..be7277b31572 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchOptions.java @@ -23,7 +23,7 @@ public class MatchOptions implements JDOMExternalizable { private boolean recursiveSearch; private boolean caseSensitiveMatch; private boolean resultIsContextMatch = false; - private FileType myFileType = StructuralSearchUtil.getDefaultFileType(); + private FileType myFileType = null; private Language myDialect = null; private SearchScope scope; @@ -268,8 +268,7 @@ public class MatchOptions implements JDOMExternalizable { } public int hashCode() { - int result; - result = (looseMatching ? 1 : 0); + int result = (looseMatching ? 1 : 0); result = 29 * result + (recursiveSearch ? 1 : 0); result = 29 * result + (caseSensitiveMatch ? 1 : 0); // @TODO support scope @@ -285,6 +284,9 @@ public class MatchOptions implements JDOMExternalizable { } public FileType getFileType() { + if (myFileType == null) { + myFileType = StructuralSearchUtil.getDefaultFileType(); + } return myFileType; } From 076f4e4551c2e9fe6f6cfd4d1221802664e80a50 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sun, 22 Feb 2015 16:10:40 +0100 Subject: [PATCH 159/231] SSR: more lenient if statement matching --- .../impl/matcher/JavaMatchingVisitor.java | 3 ++- .../impl/matcher/predicates/WithinPredicate.java | 6 +++++- .../structuralsearch/StructuralSearchTest.java | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index c8dca645f698..467b18f1778c 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -1205,9 +1205,10 @@ public class JavaMatchingVisitor extends JavaElementVisitor { public void visitIfStatement(final PsiIfStatement if1) { final PsiIfStatement if2 = (PsiIfStatement)myMatchingVisitor.getElement(); + final PsiStatement elseBranch = if1.getElseBranch(); myMatchingVisitor.setResult(myMatchingVisitor.match(if1.getCondition(), if2.getCondition()) && compareBody(if1.getThenBranch(), if2.getThenBranch()) && - compareBody(if1.getElseBranch(), if2.getElseBranch())); + (elseBranch == null || compareBody(elseBranch, if2.getElseBranch()))); } @Override diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java index c891cb1c1ec5..5b1e3f316f8b 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java @@ -4,6 +4,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.structuralsearch.MatchOptions; import com.intellij.structuralsearch.MatchResult; import com.intellij.structuralsearch.Matcher; @@ -35,6 +36,9 @@ public class WithinPredicate extends AbstractStringBasedPredicate { public boolean match(PsiElement node, PsiElement match, int start, int end, MatchContext context) { final MatchResult result = matcher.isMatchedByDownUp(match, myMatchOptions); - return result != null; + if (result == null) { + return false; + } + return PsiTreeUtil.isAncestor(result.getMatch(), match, false); } } \ No newline at end of file diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 732859261018..eebb845a4956 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -842,6 +842,18 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "return !(x);"; String s10034 = "return ('a);"; assertEquals("Find statement with parenthesized expr",2,findMatchesCount(s10033,s10034)); + + String in = "if (true) {" + + " System.out.println();" + + "} else {" + + " System.out.println();" + + "}" + + "if (true) System.out.println();"; + String pattern1 = "if ('_exp) { '_statement*; }"; + assertEquals("Find if statement with else", 2, findMatchesCount(in, pattern1)); + + String pattern2 = "if ('_exp) { '_statement*; } else { '_statement2{0,0}; }"; + assertEquals("Find if statement without else", 1, findMatchesCount(in, pattern2)); } public void testSearchClass() { From 51d506e645f17d7945578d5c5581dfef10accf8a Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 23 Feb 2015 10:36:18 +0100 Subject: [PATCH 160/231] SSR: explicitly set file type instead of depending on default file type in tests --- .../intellij/structuralsearch/SSBasedInspectionTest.java | 3 +++ .../com/intellij/structuralsearch/SSRCodeInsightTest.java | 2 ++ .../intellij/structuralsearch/StructuralReplaceTest.java | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java index ff2083ebfbfa..5ea22da14d3b 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSBasedInspectionTest.java @@ -1,6 +1,7 @@ package com.intellij.structuralsearch; import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection; import com.intellij.structuralsearch.plugin.ui.Configuration; import com.intellij.structuralsearch.plugin.ui.SearchConfiguration; @@ -20,11 +21,13 @@ public class SSBasedInspectionTest extends InspectionTestCase { List configurations = new ArrayList(); SearchConfiguration configuration = new SearchConfiguration(); MatchOptions options = new MatchOptions(); + options.setFileType(StdFileTypes.JAVA); options.setSearchPattern("int i;"); configuration.setMatchOptions(options); configurations.add(configuration); configuration = new SearchConfiguration(); options = new MatchOptions(); + options.setFileType(StdFileTypes.JAVA); options.setSearchPattern("f();"); configuration.setMatchOptions(options); configurations.add(configuration); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java index 95cd33b0845a..2f9bf669def3 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/SSRCodeInsightTest.java @@ -1,5 +1,6 @@ package com.intellij.structuralsearch; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.structuralsearch.inspection.highlightTemplate.SSBasedInspection; import com.intellij.structuralsearch.plugin.ui.Configuration; import com.intellij.structuralsearch.plugin.ui.SearchConfiguration; @@ -60,6 +61,7 @@ public class SSRCodeInsightTest extends UsefulTestCase { //search pattern final MatchOptions options = new MatchOptions(); + options.setFileType(StdFileTypes.JAVA); options.setSearchPattern(searchPattern); configuration.setMatchOptions(options); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index 250a57e3811c..a8d846767a86 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -1,5 +1,6 @@ package com.intellij.structuralsearch; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.CommonClassNames; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.ThrowableRunnable; @@ -12,6 +13,13 @@ import java.io.IOException; */ @SuppressWarnings({"ALL"}) public class StructuralReplaceTest extends StructuralReplaceTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + options.getMatchOptions().setFileType(StdFileTypes.JAVA); + } + public void testReplaceInLiterals() { String s1 = "String ID_SPEED = \"Speed\";"; String s2 = "String 'name = \"'string\";"; From 9e91955dc569c3be9706fc34357c79e3b9fad1b8 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 23 Feb 2015 10:44:22 +0100 Subject: [PATCH 161/231] SSR: simplify xml matching --- .../impl/matcher/XmlMatchingVisitor.java | 42 ++++++++----------- .../matcher/compiler/XmlCompilingVisitor.java | 24 +++++------ .../filters/XmlLexicalNodesFilter.java | 11 ++++- 3 files changed, 38 insertions(+), 39 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java index 8d102b0b2440..869451a6b202 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/XmlMatchingVisitor.java @@ -77,14 +77,15 @@ public class XmlMatchingVisitor extends XmlElementVisitor { PsiElement[] matchedNodes = another.getValue().getChildren(); if (contentChildren.length != 1) { - patternNodes = expandXmlTexts(patternNodes); - matchedNodes = expandXmlTexts(matchedNodes); + patternNodes = filterOutWhitespace(patternNodes); + matchedNodes = filterOutWhitespace(matchedNodes); } - myMatchingVisitor.setResult(myMatchingVisitor.matchSequentially( + final boolean result = myMatchingVisitor.matchSequentially( new ArrayBackedNodeIterator(patternNodes), new ArrayBackedNodeIterator(matchedNodes) - )); + ); + myMatchingVisitor.setResult(result); } } @@ -97,34 +98,27 @@ public class XmlMatchingVisitor extends XmlElementVisitor { } } - private static PsiElement[] expandXmlTexts(PsiElement[] children) { + private static PsiElement[] filterOutWhitespace(PsiElement[] children) { final List result = new ArrayList(children.length); - for(PsiElement c:children) { - if (c instanceof XmlText) { - for(PsiElement p:c.getChildren()) { - if (!(p instanceof PsiWhiteSpace)) result.add(p); + for(PsiElement child : children) { + if (child instanceof XmlText) { + final PsiElement[] grandChildren = child.getChildren(); + if (grandChildren.length == 1 && grandChildren[0] instanceof PsiWhiteSpace) { + continue; } - } else if (!(c instanceof PsiWhiteSpace)) { - result.add(c); } + result.add(child); } return PsiUtilCore.toPsiElementArray(result); } @Override public void visitXmlText(XmlText text) { - myMatchingVisitor.setResult(myMatchingVisitor.matchSequentially(text.getFirstChild(), myMatchingVisitor.getElement().getFirstChild())); - } - - @Override public void visitXmlToken(XmlToken token) { - if (token.getTokenType() == XmlTokenType.XML_DATA_CHARACTERS) { - final String text = token.getText(); - final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text); - - if (isTypedVar) { - myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(token, myMatchingVisitor.getElement())); - } else { - myMatchingVisitor.setResult(matches(text, myMatchingVisitor.getElement().getText())); - } + final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(text); + final PsiElement element = myMatchingVisitor.getElement(); + if (isTypedVar) { + myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(text, element)); + } else { + myMatchingVisitor.setResult(matches(text.getText(), element.getText())); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java index 99917ad23240..529b9deab344 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/XmlCompilingVisitor.java @@ -5,10 +5,10 @@ import com.intellij.psi.XmlRecursiveElementVisitor; import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlText; import com.intellij.psi.xml.XmlToken; +import com.intellij.structuralsearch.impl.matcher.CompiledPattern; import com.intellij.structuralsearch.impl.matcher.filters.TagValueFilter; import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler; import com.intellij.structuralsearch.impl.matcher.handlers.TopLevelMatchingHandler; -import com.intellij.structuralsearch.impl.matcher.handlers.XmlTextHandler; import com.intellij.structuralsearch.impl.matcher.strategies.XmlMatchingStrategy; /** @@ -26,17 +26,15 @@ public class XmlCompilingVisitor extends XmlRecursiveElementVisitor { super.visitElement(element); } - @Override public void visitXmlToken(XmlToken token) { - super.visitXmlToken(token); + @Override + public void visitXmlToken(XmlToken token) {} - if (token.getParent() instanceof XmlText && myCompilingVisitor.getContext().getPattern().isRealTypedVar(token)) { - final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(token); - handler.setFilter(TagValueFilter.getInstance()); + @Override + public void visitXmlText(XmlText text) { + super.visitXmlText(text); - final XmlTextHandler parentHandler = new XmlTextHandler(); - myCompilingVisitor.getContext().getPattern().setHandler(token.getParent(), parentHandler); - parentHandler.setFilter(TagValueFilter.getInstance()); - } + final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(text); + handler.setFilter(TagValueFilter.getInstance()); } @Override public void visitXmlTag(XmlTag xmlTag) { @@ -45,9 +43,9 @@ public class XmlCompilingVisitor extends XmlRecursiveElementVisitor { myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() - 1); if (myCompilingVisitor.getCodeBlockLevel() == 1) { - myCompilingVisitor.getContext().getPattern().setStrategy(XmlMatchingStrategy.getInstance()); - myCompilingVisitor.getContext().getPattern() - .setHandler(xmlTag, new TopLevelMatchingHandler(myCompilingVisitor.getContext().getPattern().getHandler(xmlTag))); + final CompiledPattern pattern = myCompilingVisitor.getContext().getPattern(); + pattern.setStrategy(XmlMatchingStrategy.getInstance()); + pattern.setHandler(xmlTag, new TopLevelMatchingHandler(pattern.getHandler(xmlTag))); } } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java index 89c295ce1d80..e59447312ed7 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/filters/XmlLexicalNodesFilter.java @@ -1,7 +1,8 @@ package com.intellij.structuralsearch.impl.matcher.filters; +import com.intellij.psi.PsiErrorElement; +import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.XmlElementVisitor; -import com.intellij.psi.xml.XmlText; /** * @author Eugene.Kudelevsky @@ -13,7 +14,13 @@ public class XmlLexicalNodesFilter extends XmlElementVisitor { this.myLexicalNodesFilter = lexicalNodesFilter; } - @Override public void visitXmlText(XmlText text) { + @Override + public void visitWhiteSpace(PsiWhiteSpace space) { + myLexicalNodesFilter.setResult(true); + } + + @Override + public void visitErrorElement(PsiErrorElement element) { myLexicalNodesFilter.setResult(true); } } From 0ad9e4fb83aa01705552a126eed18eae9aea7143 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 23 Feb 2015 19:49:22 +0100 Subject: [PATCH 162/231] SSR: fix within predicate bugs --- .../intellij/structuralsearch/Matcher.java | 8 +-- .../impl/matcher/MatcherImpl.java | 38 ++++++----- .../matcher/predicates/WithinPredicate.java | 12 ++-- .../StructuralSearchTest.java | 67 ++++++++++--------- 4 files changed, 66 insertions(+), 59 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java b/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java index 594686e14d49..747c17625095 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/Matcher.java @@ -4,7 +4,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.structuralsearch.impl.matcher.MatcherImpl; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -75,10 +75,10 @@ public class Matcher extends MatcherImpl { * @throws MalformedPatternException * @throws UnsupportedPatternException */ - @Nullable - public MatchResult isMatchedByDownUp(PsiElement element,MatchOptions options) throws + @NotNull + public List matchByDownUp(PsiElement element, MatchOptions options) throws MalformedPatternException, UnsupportedPatternException { - return super.isMatchedByDownUp(element, options); + return super.matchByDownUp(element, options); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java index 678b99cf2146..1597f2f2d87b 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java @@ -41,6 +41,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.SoftReference; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -627,15 +628,11 @@ public class MatcherImpl { } } - @Nullable - protected MatchResult isMatchedByDownUp(PsiElement element, final MatchOptions options) { + @NotNull + protected List matchByDownUp(PsiElement element, final MatchOptions options) { final CollectingMatchResultSink sink = new CollectingMatchResultSink(); - CompiledPattern compiledPattern = prepareMatching(sink, options); - - if (compiledPattern== null) { - assert false; - return null; - } + final CompiledPattern compiledPattern = prepareMatching(sink, options); + matchContext.setShouldRecursivelyMatch(false); PsiElement targetNode = compiledPattern.getTargetNode(); PsiElement elementToStartMatching = null; @@ -647,21 +644,26 @@ public class MatcherImpl { assert !compiledPattern.getNodes().hasNext(); compiledPattern.getNodes().rewind(); + element = element.getParent(); + if (element == null) { + return Collections.emptyList(); + } while (element.getClass() != targetNode.getClass()) { element = element.getParent(); - if (element == null) return null; + if (element == null) return Collections.emptyList(); } elementToStartMatching = element; } } else { - targetNode = StructuralSearchUtil.getProfileByPsiElement(element).extendMatchedByDownUp(targetNode); + final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(element); + if (profile == null) return Collections.emptyList(); + targetNode = profile.extendMatchedByDownUp(targetNode); MatchingHandler handler = null; while (element.getClass() == targetNode.getClass() || - compiledPattern.isTypedVar(targetNode) && compiledPattern.getHandler(targetNode).canMatch(targetNode, element) - ) { + compiledPattern.isTypedVar(targetNode) && compiledPattern.getHandler(targetNode).canMatch(targetNode, element)) { handler = compiledPattern.getHandler(targetNode); handler.setPinnedElement(element); elementToStartMatching = element; @@ -670,21 +672,21 @@ public class MatcherImpl { targetNode = targetNode.getParent(); if (options.isLooseMatching()) { - element = StructuralSearchUtil.getProfileByPsiElement(element).updateCurrentNode(element); - targetNode = StructuralSearchUtil.getProfileByPsiElement(element).updateCurrentNode(targetNode); + element = profile.updateCurrentNode(element); + targetNode = profile.updateCurrentNode(targetNode); } } - if (!(handler instanceof TopLevelMatchingHandler)) return null; + if (!(handler instanceof TopLevelMatchingHandler)) return Collections.emptyList(); } assert targetNode != null : "Could not match down up when no target node"; + System.out.println("elementToStartMatching = " + elementToStartMatching.getText()); match(elementToStartMatching); matchContext.getSink().matchingFinished(); - final int matchCount = sink.getMatches().size(); - assert matchCount <= 1; - return matchCount > 0 ? sink.getMatches().get(0) : null; + final List matches = sink.getMatches(); + return matches; } private class MatchOneVirtualFile extends MatchOneFile { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java index 5b1e3f316f8b..fc7984680db9 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/WithinPredicate.java @@ -11,6 +11,8 @@ import com.intellij.structuralsearch.Matcher; import com.intellij.structuralsearch.impl.matcher.MatchContext; import com.intellij.structuralsearch.impl.matcher.compiler.PatternCompiler; +import java.util.List; + /** * @author Maxim.Mossienko */ @@ -35,10 +37,12 @@ public class WithinPredicate extends AbstractStringBasedPredicate { } public boolean match(PsiElement node, PsiElement match, int start, int end, MatchContext context) { - final MatchResult result = matcher.isMatchedByDownUp(match, myMatchOptions); - if (result == null) { - return false; + final List results = matcher.matchByDownUp(match, myMatchOptions); + for (MatchResult result : results) { + if (PsiTreeUtil.isAncestor(result.getMatch(), match, false)) { + return true; + } } - return PsiTreeUtil.isAncestor(result.getMatch(), match, false); + return false; } } \ No newline at end of file diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index eebb845a4956..ef53d82b13ed 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -1,6 +1,5 @@ package com.intellij.structuralsearch; -import com.intellij.idea.Bombed; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.psi.*; import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil; @@ -9,7 +8,6 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; /** @@ -2740,12 +2738,10 @@ public class StructuralSearchTest extends StructuralSearchTestCase { options.setFileType(StdFileTypes.JAVA); for(PsiVariable var:vars) { - final MatchResult matchResult = testMatcher.isMatchedByDownUp(var, options); - if (matchResult != null) results.add(matchResult); - assertTrue( - (var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && matchResult != null) || - matchResult == null - ); + final List matchResult = testMatcher.matchByDownUp(var, options); + results.addAll(matchResult); + assertTrue((var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && !matchResult.isEmpty()) || + matchResult.isEmpty()); } assertEquals(2, results.size()); @@ -2764,12 +2760,10 @@ public class StructuralSearchTest extends StructuralSearchTestCase { for(PsiVariable var:vars) { final PsiTypeElement typeElement = var.getTypeElement(); - final MatchResult matchResult = testMatcher.isMatchedByDownUp(typeElement, options); - if (matchResult != null) results.add(matchResult); - assertTrue( - (var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && matchResult != null) || - matchResult == null - ); + final List matchResult = testMatcher.matchByDownUp(typeElement, options); + results.addAll(matchResult); + assertTrue((var instanceof PsiParameter && var.getParent() instanceof PsiCatchSection && !matchResult.isEmpty()) || + matchResult.isEmpty()); } assertEquals(1, results.size()); @@ -2778,7 +2772,6 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals("Type2", result.getMatchImage()); } - @Bombed(day = 28, description = "support it", month = Calendar.JULY, user = "maxim.mossienko") public void _testContainsPredicate() { String s1 = "{{\n" + " int a;\n" + @@ -2820,35 +2813,43 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals(2,findMatchesCount(s1, s2)); assertEquals(1,findMatchesCount(s1, s2_2)); - // TODO: xxx - //String s3 = "if (true) {\n" + - // " if (true) return;\n" + - // " int a = 1;\n" + - // "}\n else if (true) {\n" + - // " return;\n" + - // "}"; - //assertEquals(2,findMatchesCount(s3, s2)); - //assertEquals(1,findMatchesCount(s3, s2_2)); + String s3 = "if (true) {\n" + + " if (true) return;\n" + + " int a = 1;\n" + + "}\n" + + "else if (true) {\n" + + " int b = 2;\n" + + " return;\n" + + "}\n" + + "int c = 3;\n"; + assertEquals(2,findMatchesCount(s3, s2)); + assertEquals(1,findMatchesCount(s3, s2_2)); } public void testWithinPredicate2() { String s3 = "class C {\n" + " void aaa() {\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + - " LOG.debug(true);\n" + + " LOG.debug(1);\n" + + " LOG.debug(2);\n" + + " LOG.debug(3);\n" + + " LOG.debug(4);\n" + + " LOG.debug(5);\n" + " if (true) {\n" + - " LOG.debug(true);\n" + + " LOG.debug(6);\n" + " }\n" + - " if (true) LOG.debug(true);\n" + - " if (true) { int 1 = 1; } else { LOG.debug(true); }\n" + + " if (true) LOG.debug(7);\n" + + " if (true) { int 1 = 1; } else { LOG.debug(8); }\n" + + " if (true) {\n" + + " if (true) {}\n" + + " if (true) {}\n" + + " } else{\n" + + " LOG.debug(9);\n" + + " }" + " }" + "}"; String s4 = "LOG.debug('_params*:[!within( \"if('_a) { 'st*; }\" )]);"; - assertEquals(6,findMatchesCount(s3, s4)); + assertEquals(7,findMatchesCount(s3, s4)); } public void testMultiStatementPatternWithTypedVariable() throws Exception { From 64ce89956bfa21f5f99d72d149d23dfe644231d9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 13:41:04 +0100 Subject: [PATCH 163/231] missed inspectionFinished (IDEA-136834) --- .../intellij/codeInsight/daemon/impl/LocalInspectionsPass.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index f4894afc9eb1..3a9401308de1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -289,6 +289,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } advanceProgress(1); + tool.inspectionFinished(session, holder); if (holder.hasResults()) { appendDescriptors(myFile, holder.getResults(), toolWrapper); } From 8b7325aae54b83db8edbe9f81add12cc048f8aa9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 14:05:36 +0100 Subject: [PATCH 164/231] testdata for IDEA-136856 --- .../lambda/regression/IDEA136856.java | 43 +++++++++++++++ .../daemon/lambda/Java8RegressionTest.java | 54 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java new file mode 100644 index 000000000000..7b75b0feba20 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136856.java @@ -0,0 +1,43 @@ +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collector; + +class Test { + public static final Collector, Optional> toSingleton() { + return Collector.of( + AtomicReference::new, + (ref, v) -> { + if (!ref.compareAndSet(null, v) && v != null) { + throw new IllegalStateException("There is only one elvis."); + } + }, + (left, right) -> setOrFail(left, right.get()), + ref -> Optional.of(ref.get()) + ); + } + + public static final Collector, Optional> toSingleton1() { + return Collector.of( + AtomicReference::new, + (ref, v) -> setOrFail(ref, v), + (left, right) -> setOrFail(left, right.get()), + ref -> Optional.of(ref.get()) + ); + } + + public static final Collector, Optional> toSingleton2() { + return Collector.of( + AtomicReference::new, + Test::setOrFail, + (left, right) -> setOrFail(left, right.get()), + ref -> Optional.of(ref.get()) + ); + } + + private static final AtomicReference setOrFail(AtomicReference ref, T v) { + if (!ref.compareAndSet(null, v) && v != null) { + throw new IllegalStateException("There is only one elvis."); + } + return ref; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java new file mode 100644 index 000000000000..636909c30851 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2015 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.codeInsight.daemon.lambda; + +import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; +import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; +import com.intellij.idea.Bombed; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.testFramework.IdeaTestUtil; +import org.jetbrains.annotations.NonNls; + +import java.util.Calendar; + +public class Java8RegressionTest extends LightDaemonAnalyzerTestCase { + @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/regression"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + enableInspectionTool(new UnusedDeclarationInspection()); + } + + public void testIDEA136856() throws Exception { + doTest(); + } + + private void doTest() { + doTest(false); + } + + private void doTest(boolean warnings) { + IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable()); + doTest(BASE_PATH + "/" + getTestName(false) + ".java", warnings, false); + } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } +} From 4819405128c341ba8ea8cfb2168d0f0c8ef6e07d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 19:39:32 +0100 Subject: [PATCH 165/231] ensure resolve is not cached during overload resolution --- .../psi/infos/MethodCandidateInfo.java | 12 +++++------ .../resolve/SecondConflictResolution.java | 21 +++++++++++++++++++ .../daemon/lambda/TypeInference18Test.java | 9 ++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index 063f2b81934e..276fd77f0e3f 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -312,17 +312,17 @@ public class MethodCandidateInfo extends CandidateInfo{ public static CurrentCandidateProperties getCurrentMethod(PsiElement context) { + if (isOverloadCheck()) { + ourOverloadGuard.prohibitResultCaching(ourOverloadGuard.currentStack().get(0)); + } final Map currentMethodCandidates = CURRENT_CANDIDATE.get(); return currentMethodCandidates != null ? currentMethodCandidates.get(context) : null; } public static void updateSubstitutor(PsiElement context, PsiSubstitutor newSubstitutor) { - final Map currentMethodCandidates = CURRENT_CANDIDATE.get(); - if (currentMethodCandidates != null) { - final CurrentCandidateProperties properties = currentMethodCandidates.get(context); - if (properties != null) { - properties.setSubstitutor(newSubstitutor); - } + CurrentCandidateProperties candidateProperties = getCurrentMethod(context); + if (candidateProperties != null) { + candidateProperties.setSubstitutor(newSubstitutor); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java new file mode 100644 index 000000000000..ac48bcb9dc8b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/SecondConflictResolution.java @@ -0,0 +1,21 @@ + +import java.util.*; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; + +abstract class Token { + + + private static B getMode(Optional> max){ + return max + .flatMap(e -> Optional.of(new B<>(Long.valueOf(e.getValue().longValue())))) + .get(); + } + + static class B { + public B(K k) {} + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java index 8a9a451c14da..5d8cd07c3270 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java @@ -21,6 +21,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.ResolveTestCase; @@ -30,6 +31,14 @@ public class TypeInference18Test extends ResolveTestCase { doTest(); } + public void testSecondConflictResolution() throws Exception { + PsiReference ref = configureByFile("/codeInsight/daemonCodeAnalyzer/lambda/resolve/" + getTestName(false) + ".java"); + assertNotNull(ref); + PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(ref.getElement(), PsiMethodCallExpression.class); + assertNotNull(methodCallExpression); + assertNotNull(methodCallExpression.resolveMethod()); + } + private LanguageLevel myOldLanguageLevel; @Override From ccee6ee514c48923fd1fa5c83ff5452af01fe385 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 20:01:01 +0100 Subject: [PATCH 166/231] disarmed bombs --- .../daemon/lambda/FindFunctionalInterfaceTest.java | 2 -- .../codeInsight/daemon/lambda/Java8RegressionTest.java | 3 --- .../codeInsight/daemon/lambda/NewLambdaHighlightingTest.java | 2 -- .../daemon/lambda/NewMethodRefHighlightingTest.java | 4 ---- 4 files changed, 11 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java index 64b013d44df7..2630d5f999a6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FindFunctionalInterfaceTest.java @@ -16,7 +16,6 @@ package com.intellij.codeInsight.daemon.lambda; import com.intellij.JavaTestUtil; -import com.intellij.idea.Bombed; import com.intellij.psi.*; import com.intellij.psi.search.searches.FunctionalExpressionSearch; import com.intellij.psi.search.searches.ReferencesSearch; @@ -25,7 +24,6 @@ import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; -import java.util.Calendar; import java.util.Collection; public class FindFunctionalInterfaceTest extends LightCodeInsightFixtureTestCase { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java index 636909c30851..ea3d7f543801 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java @@ -17,14 +17,11 @@ package com.intellij.codeInsight.daemon.lambda; import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; -import com.intellij.idea.Bombed; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.testFramework.IdeaTestUtil; import org.jetbrains.annotations.NonNls; -import java.util.Calendar; - public class Java8RegressionTest extends LightDaemonAnalyzerTestCase { @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/regression"; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index d53205a820cb..00915527a2cb 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -80,7 +80,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testLiftedIntersectionType() { doTest(); } public void testInferenceFromReturnStatements() { doTest(); } public void testDownUpThroughLambdaReturnStatements() { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testIDEA124547() { doTest(); } public void testIDEA118362() { doTest(); } public void testIDEA126056() { doTest(); } @@ -168,7 +167,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testIDEA127124() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 60ad003549b3..810019f54bd0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -19,15 +19,12 @@ import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; -import com.intellij.idea.Bombed; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.testFramework.IdeaTestUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.util.Calendar; - public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef"; @@ -373,7 +370,6 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testIDEA132379() throws Exception { doTest(); } From cf0eb93bd53a5256a4e02c285cec4c73a3f329fd Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 23 Feb 2015 21:35:02 +0100 Subject: [PATCH 167/231] new inference: ensure only proper checked exceptions are proceed --- .../CheckedExceptionCompatibilityConstraint.java | 11 +++++++++-- .../daemon/lambda/NewLambdaHighlightingTest.java | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java index 23460fbda4fc..87eb8b804b08 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -18,10 +18,12 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Condition; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; @@ -45,7 +47,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai } @Override - public boolean reduce(InferenceSession session, List constraints) { + public boolean reduce(final InferenceSession session, List constraints) { if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) { return true; } @@ -111,7 +113,12 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai } }); if (exceptions != null) { - thrownTypes.addAll(exceptions); + thrownTypes.addAll(ContainerUtil.filter(exceptions, new Condition() { + @Override + public boolean value(PsiClassType type) { + return session.isProperType(type) && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_EXCEPTION); + } + })); } } } else { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 00915527a2cb..ca5ce7e44e96 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -138,7 +138,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(year = 2015, month = Calendar.MARCH, day = 30) public void testCheckedExceptionsConstraintsSubstitutions() throws Exception { doTest(); } From 4238e9aedb14a0d88133981e6d90934af70e304a Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 13:38:56 +0100 Subject: [PATCH 168/231] cleanup --- .../options/ShareSchemeDialog.java | 49 ----------------- .../application/options/ShareSchemePanel.form | 53 ------------------- .../application/options/ShareSchemePanel.java | 41 -------------- 3 files changed, 143 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java delete mode 100644 platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form delete mode 100644 platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java diff --git a/platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java b/platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java deleted file mode 100644 index 22efc052e9ef..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/ShareSchemeDialog.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2000-2009 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.application.options; - -import com.intellij.openapi.options.Scheme; -import com.intellij.openapi.ui.DialogWrapper; - -import javax.swing.*; - -public class ShareSchemeDialog extends DialogWrapper { - private final ShareSchemePanel myShareSchemePanel; - - public ShareSchemeDialog() { - super(true); - myShareSchemePanel = new ShareSchemePanel(); - setTitle("Share Scheme"); - init(); - } - - public void init(Scheme scheme){ - myShareSchemePanel.setName(scheme.getName()); - } - - protected JComponent createCenterPanel() { - return myShareSchemePanel.getPanel(); - } - - public String getName(){ - return myShareSchemePanel.getName(); - } - - public String getDescription(){ - return myShareSchemePanel.getDescription(); - } - -} diff --git a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form b/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form deleted file mode 100644 index e1082de419f1..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.form +++ /dev/null @@ -1,53 +0,0 @@ - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    diff --git a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java b/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java deleted file mode 100644 index 708004896633..000000000000 --- a/platform/platform-impl/src/com/intellij/application/options/ShareSchemePanel.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2009 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.application.options; - -import javax.swing.*; - - -public class ShareSchemePanel { - private JTextField mySharedSchemeName; - private JTextArea mySharedSchemeDescription; - private JPanel myPanel; - - public String getName(){ - return mySharedSchemeName.getText(); - } - - public String getDescription(){ - return mySharedSchemeDescription.getText(); - } - - public JPanel getPanel() { - return myPanel; - } - - public void setName(final String name) { - mySharedSchemeName.setText(name); - } -} From 849c94433bfdd63e9c0a293143e3226431250a80 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 13:49:57 +0100 Subject: [PATCH 169/231] deprecate unused StorageId, Storage#isDefault --- .../util/base/TextDiffSettingsHolder.java | 6 +- .../impl/stores/ComponentStoreImpl.java | 1 - .../impl/stores/DirectoryBasedStorage.java | 30 +++------ .../impl/stores/FileBasedStorage.java | 4 +- .../impl/stores/SaveSessionBase.java | 63 +++++++++++++++++++ .../stores}/StateStorageBase.java | 6 +- .../impl/stores/XmlElementStorage.java | 22 +------ .../project/impl/ProjectManagerImpl.java | 6 +- .../intellij/openapi/components/Storage.java | 7 ++- .../openapi/components/StorageId.java | 4 +- .../impl/stores/DefaultStateSerializer.java | 39 +----------- ...SkipDefaultValuesSerializationFilters.java | 5 +- 12 files changed, 94 insertions(+), 99 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java rename platform/platform-impl/src/com/intellij/openapi/components/{store => impl/stores}/StateStorageBase.java (91%) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java index a583068b2668..f73a10053abe 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.java @@ -31,15 +31,15 @@ import java.util.Map; @State( name = "TextDiffSettings", - storages = {@Storage( - file = DiffUtil.DIFF_CONFIG)}) + storages = @Storage(file = DiffUtil.DIFF_CONFIG) +) public class TextDiffSettingsHolder implements PersistentStateComponent { public static final Key KEY = Key.create("TextDiffSettings"); public static final int[] CONTEXT_RANGE_MODES = {1, 2, 4, 8, -1}; public static final String[] CONTEXT_RANGE_MODE_LABELS = {"1", "2", "4", "8", "Disable"}; - private static class SharedSettings { + private final static class SharedSettings { // Fragments settings public int CONTEXT_RANGE = 4; } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index fef8f4f8bac6..8e15a8f61f78 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -22,7 +22,6 @@ import com.intellij.openapi.components.StateStorage.SaveSession; import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.components.impl.stores.StateStorageManager.ExternalizationSession; import com.intellij.openapi.components.store.ReadOnlyModificationException; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java index 199d70123ca9..373d9c38f9a5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,14 +18,15 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.StateSplitter; +import com.intellij.openapi.components.StateStorageException; +import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.components.store.ReadOnlyModificationException; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.editor.DocumentRunnable; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -178,7 +179,7 @@ public class DirectoryBasedStorage extends StateStorageBase pair : storage.mySplitter.splitState(compositeState)) { + for (Pair pair : storage.mySplitter.splitState(element)) { removedFileNames.remove(pair.second); doSetState(componentName, pair.second, pair.first); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java index 53ac35c58ee3..6142c0823986 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -106,7 +106,7 @@ public class FileBasedStorage extends XmlElementStorage { } } - private class FileSaveSession extends XmlElementStorageSaveSession { + private class FileSaveSession extends XmlElementStorageSaveSession { protected FileSaveSession(@NotNull StorageData storageData) { super(storageData); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java new file mode 100644 index 000000000000..b46d88ea346b --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.components.impl.stores; + +import com.intellij.openapi.components.StateStorage; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; +import com.intellij.util.xmlb.XmlSerializer; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class SaveSessionBase implements StateStorage.SaveSession, StateStorage.ExternalizationSession { + private SkipDefaultValuesSerializationFilters serializationFilter; + + @SuppressWarnings("deprecation") + @Override + public final void setState(@NotNull Object component, @NotNull String componentName, @NotNull Object state, Storage storageSpec) { + Element element; + try { + if (state instanceof Element) { + element = (Element)state; + } + else if (state instanceof JDOMExternalizable) { + element = new Element("temp_element"); + ((JDOMExternalizable)state).writeExternal(element); + } + else { + if (serializationFilter == null) { + serializationFilter = new SkipDefaultValuesSerializationFilters(); + } + element = XmlSerializer.serializeIfNotDefault(state, serializationFilter); + } + } + catch (WriteExternalException e) { + StateStorageBase.LOG.debug(e); + return; + } + catch (Throwable e) { + StateStorageBase.LOG.error("Unable to serialize " + componentName + " state", e); + return; + } + + setSerializedState(component, componentName, element); + } + + protected abstract void setSerializedState(@NotNull Object component, @NotNull String componentName, @Nullable Element element); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/components/store/StateStorageBase.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.java similarity index 91% rename from platform/platform-impl/src/com/intellij/openapi/components/store/StateStorageBase.java rename to platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.java index da38c311e134..fb02c973e240 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/store/StateStorageBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.components.store; +package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.impl.stores.DefaultStateSerializer; -import com.intellij.openapi.components.impl.stores.StorageDataBase; import com.intellij.openapi.diagnostic.Logger; import org.jdom.Element; import org.jetbrains.annotations.NotNull; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index 4b6624d6cad0..78b624949979 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,11 +17,8 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.RoamingType; import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; @@ -175,7 +172,7 @@ public abstract class XmlElementStorage extends StateStorageBase { } } - protected abstract class XmlElementStorageSaveSession implements SaveSession, ExternalizationSession { + protected abstract class XmlElementStorageSaveSession extends SaveSessionBase { private final StorageData myOriginalStorageData; private StorageData myCopiedStorageData; @@ -192,20 +189,7 @@ public abstract class XmlElementStorage extends StateStorageBase { } @Override - public final void setState(@NotNull Object component, @NotNull String componentName, @NotNull Object state, @Nullable Storage storageSpec) { - Element element; - try { - element = DefaultStateSerializer.serializeState(state, storageSpec); - } - catch (WriteExternalException e) { - LOG.debug(e); - return; - } - catch (Throwable e) { - LOG.error("Unable to serialize " + componentName + " state", e); - return; - } - + protected void setSerializedState(@NotNull Object component, @NotNull String componentName, @Nullable Element element) { if (myCopiedStorageData == null) { myCopiedStorageData = StorageData.setStateAndCloneIfNeed(componentName, element, myOriginalStorageData, myNewLiveStates); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index f12e25ba113d..401d3e5f9c09 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -29,12 +29,8 @@ import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.components.*; -import com.intellij.openapi.components.impl.stores.ComponentStoreImpl; +import com.intellij.openapi.components.impl.stores.*; import com.intellij.openapi.components.impl.stores.ComponentStoreImpl.ReloadComponentStoreStatus; -import com.intellij.openapi.components.impl.stores.FileBasedStorage; -import com.intellij.openapi.components.impl.stores.StateStorageManager; -import com.intellij.openapi.components.impl.stores.StorageUtil; -import com.intellij.openapi.components.store.StateStorageBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.*; diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java b/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java index 152cc036347c..0bdcbbfa6f28 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/Storage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,12 @@ import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface Storage { @NonNls String id() default "default"; + + @Deprecated boolean isDefault() default true; + @NonNls String file() default ""; + StorageScheme scheme() default StorageScheme.DEFAULT; /** @@ -39,5 +43,6 @@ public @interface Storage { RoamingType roamingType() default RoamingType.PER_USER; Class storageClass() default StateStorage.class; + Class stateSplitter() default StateSplitterEx.class; } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java b/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java index 0baf9e6ebd05..d00e69aae56e 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/StorageId.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.openapi.components; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) +@Deprecated public @interface StorageId { String value(); } \ No newline at end of file diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java index d882ca15be83..3d1bb2240528 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DefaultStateSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,20 +16,14 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.StorageId; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.ReflectionUtil; -import com.intellij.util.xmlb.Accessor; -import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; import com.intellij.util.xmlb.XmlSerializationException; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @SuppressWarnings({"deprecation"}) @@ -39,37 +33,6 @@ public class DefaultStateSerializer { private DefaultStateSerializer() { } - @Nullable - static Element serializeState(@NotNull Object state, @Nullable final Storage storage) throws WriteExternalException { - if (state instanceof Element) { - return (Element)state; - } - else if (state instanceof JDOMExternalizable) { - Element element = new Element("temp_element"); - ((JDOMExternalizable)state).writeExternal(element); - return element; - } - else { - return XmlSerializer.serializeIfNotDefault(state, new SkipDefaultValuesSerializationFilters() { - @Override - protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { - if (!super.accepts(accessor, bean, beanValue)) { - return false; - } - - if (storage != null) { - StorageId storageId = accessor.getAnnotation(StorageId.class); - if (storageId != null && !storageId.value().equals(storage.id())) { - return false; - } - return storage.isDefault(); - } - return true; - } - }); - } - } - @SuppressWarnings({"unchecked"}) @Nullable public static T deserializeState(@Nullable Element stateElement, Class stateClass, @Nullable T mergeInto) throws XmlSerializationException { diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java index f44785f6991c..db5819a9cc01 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import com.intellij.openapi.util.Comparing; @@ -31,7 +30,7 @@ public class SkipDefaultValuesSerializationFilters extends SerializationFilterBa @Override protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { - final Object defValue = accessor.read(getDefaultBean(bean)); + Object defValue = accessor.read(getDefaultBean(bean)); if (defValue instanceof Element && beanValue instanceof Element) { return !JDOMUtil.areElementsEqual((Element)beanValue, (Element)defValue); } From d21b7062bb3012042d1feed039f70a6f929f4c1f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 16:24:53 +0100 Subject: [PATCH 170/231] Persistence state classes doesn't have to implement "equals" anymore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you don’t implement “equals” in your sub state class, XmlSerializer cannot check it for defaults. TextDiffSettingsHolder.State.SHARED_SETTINGS = new SharedSettings(); The problem — “new SharedSettings()” is not equals to “new SharedSettings()”. As result, user gets even if SkipDefaultValuesSerializationFilters is used. While I dream about Kotlin, I can’t fight anymore against Java-developers. XmlSerializer can throw warning in this case, but to simplify developer life, it will compare objects by serializable fields, but not by reference (if equals is not implemented). --- .../compiler/CompilerConfigurationImpl.java | 6 +- .../src/com/intellij/ide/ui/UISettings.java | 2 +- .../PersistableCodeStyleSchemes.java | 4 +- .../impl/stores/SaveSessionBase.java | 6 +- .../com/intellij/util/xmlb/BeanBinding.java | 24 +++++- .../com/intellij/util/xmlb/FieldAccessor.java | 7 +- .../util/xmlb/SerializationFilter.java | 4 +- .../util/xmlb/SerializationFilterBase.java | 7 +- ...SkipDefaultValuesSerializationFilters.java | 3 +- .../xmlb/SkipDefaultsSerializationFilter.java | 85 +++++++++++++++++++ .../intellij/util/xmlb/SmartSerializer.java | 7 +- .../com/intellij/util/xmlb/XmlSerializer.java | 4 +- .../intellij/util/xmlb/XmlSerializerTest.java | 13 ++- .../XDebuggerBreakpointsContextProvider.java | 4 +- .../context/XDebuggerWatchesProvider.java | 4 +- 15 files changed, 142 insertions(+), 38 deletions(-) create mode 100644 platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java index 4edda91e2dd6..fc3cf13b92db 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -142,11 +142,11 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements Element state = new Element("state"); XmlSerializer.serializeInto(myState, state, new SkipDefaultValuesSerializationFilters() { @Override - protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { if (myState.compilerWasSpecified && "DEFAULT_COMPILER".equals(accessor.getName())) { return true; } - return super.accepts(accessor, bean, beanValue); + return super.accepts(accessor, bean); } }); diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java index 055fbc8ca6d7..d2f9b41fde60 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java @@ -184,7 +184,7 @@ public class UISettings extends SimpleModificationTracker implements PersistentS public static class FontFilter implements SerializationFilter { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { UISettings settings = (UISettings)bean; return !hasDefaultFontSetting(settings); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java index 11b3a65a1318..4cae3d3eda6e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PersistableCodeStyleSchemes.java @@ -49,9 +49,9 @@ class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements Persis public Element getState() { return XmlSerializer.serialize(this, new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { if ("CURRENT_SCHEME_NAME".equals(accessor.getName())) { - return bean != null && !DEFAULT_SCHEME_NAME.equals(accessor.read(bean)); + return !DEFAULT_SCHEME_NAME.equals(accessor.read(bean)); } else { return accessor.getValueClass().equals(String.class); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java index b46d88ea346b..9c100643314e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/SaveSessionBase.java @@ -19,14 +19,14 @@ import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.Storage; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.WriteExternalException; -import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; +import com.intellij.util.xmlb.SkipDefaultsSerializationFilter; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; abstract class SaveSessionBase implements StateStorage.SaveSession, StateStorage.ExternalizationSession { - private SkipDefaultValuesSerializationFilters serializationFilter; + private SkipDefaultsSerializationFilter serializationFilter; @SuppressWarnings("deprecation") @Override @@ -42,7 +42,7 @@ abstract class SaveSessionBase implements StateStorage.SaveSession, StateStorage } else { if (serializationFilter == null) { - serializationFilter = new SkipDefaultValuesSerializationFilters(); + serializationFilter = new SkipDefaultsSerializationFilter(); } element = XmlSerializer.serializeIfNotDefault(state, serializationFilter); } diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index 884b7e2aa656..ad15638fff36 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -39,7 +39,7 @@ import java.util.*; import java.util.List; class BeanBinding extends Binding { - private static final Logger LOG = Logger.getInstance(BeanBinding.class); + static final Logger LOG = Logger.getInstance(BeanBinding.class); private static final Map> ourAccessorCache = ContainerUtil.createConcurrentSoftValueMap(); @@ -47,7 +47,7 @@ class BeanBinding extends Binding { @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private Binding[] myBindings; - private final Class myBeanClass; + final Class myBeanClass; public BeanBinding(@NotNull Class beanClass, @Nullable Accessor accessor) { super(accessor); @@ -86,7 +86,13 @@ class BeanBinding extends Binding { public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter) { for (Binding binding : myBindings) { Accessor accessor = binding.getAccessor(); - if (!filter.accepts(accessor, o)) { + + if (filter instanceof SkipDefaultsSerializationFilter) { + if (((SkipDefaultsSerializationFilter)filter).equal(binding, o)) { + continue; + } + } + else if (!filter.accepts(accessor, o)) { continue; } @@ -121,6 +127,16 @@ class BeanBinding extends Binding { return instance; } + boolean equalByFields(@NotNull Object currentValue, @NotNull Object defaultValue, @NotNull SkipDefaultsSerializationFilter filter) { + for (Binding binding : myBindings) { + Accessor accessor = binding.getAccessor(); + if (!filter.equal(binding, accessor.read(currentValue), accessor.read(defaultValue))) { + return false; + } + } + return true; + } + @NotNull public TObjectFloatHashMap computeBindingWeights(@NotNull LinkedHashSet accessorNameTracker) { TObjectFloatHashMap weights = new TObjectFloatHashMap(accessorNameTracker.size()); diff --git a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java index c7fd18abad65..fdb1eab69768 100644 --- a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import org.jetbrains.annotations.NonNls; @@ -39,7 +38,7 @@ class FieldAccessor implements Accessor { return myField.get(o); } catch (IllegalAccessException e) { - throw new XmlSerializationException("Reading "+myField, e); + throw new XmlSerializationException("Reading " + myField, e); } } @@ -52,7 +51,7 @@ class FieldAccessor implements Accessor { myField.set(o, XmlSerializerImpl.convert(value, type)); } catch (IllegalAccessException e) { - throw new XmlSerializationException("Writing "+myField,e); + throw new XmlSerializationException("Writing " + myField, e); } } diff --git a/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java index 01f6f68f4fd1..f12f3647952f 100644 --- a/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java +++ b/platform/util/src/com/intellij/util/xmlb/SerializationFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -18,5 +18,5 @@ package com.intellij.util.xmlb; import org.jetbrains.annotations.NotNull; public interface SerializationFilter { - boolean accepts(@NotNull Accessor accessor, Object bean); + boolean accepts(@NotNull Accessor accessor, @NotNull Object bean); } diff --git a/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java b/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java index 7c1cb2b51795..6731bcaf7698 100644 --- a/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java +++ b/platform/util/src/com/intellij/util/xmlb/SerializationFilterBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,10 +20,7 @@ import org.jetbrains.annotations.Nullable; public abstract class SerializationFilterBase implements SerializationFilter { @Override - public final boolean accepts(@NotNull Accessor accessor, Object bean) { - if (bean == null) { - return true; - } + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accepts(accessor, bean, accessor.read(bean)); } diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java index db5819a9cc01..559ad12f8dab 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java @@ -39,7 +39,8 @@ public class SkipDefaultValuesSerializationFilters extends SerializationFilterBa } } - private Object getDefaultBean(@NotNull Object bean) { + @NotNull + Object getDefaultBean(@NotNull Object bean) { Class c = bean.getClass(); Object o = myDefaultBeans.get(c); if (o == null) { diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java new file mode 100644 index 000000000000..f138b621e2ad --- /dev/null +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2015 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.util.xmlb; + +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.ThreeState; +import gnu.trove.THashMap; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public final class SkipDefaultsSerializationFilter extends SkipDefaultValuesSerializationFilters { + private Map, ThreeState> hasEqualMethod; + + boolean equal(@NotNull Binding binding, @NotNull Object bean) { + Accessor accessor = binding.getAccessor(); + return equal(binding, accessor.read(bean), accessor.read(getDefaultBean(bean))); + } + + boolean equal(@Nullable Binding binding, @Nullable Object currentValue, @Nullable Object defaultValue) { + if (defaultValue instanceof Element && currentValue instanceof Element) { + return JDOMUtil.areElementsEqual((Element)currentValue, (Element)defaultValue); + } + else { + if (currentValue == defaultValue) { + return true; + } + if (currentValue == null || defaultValue == null) { + return false; + } + + if (binding instanceof BasePrimitiveBinding) { + Binding referencedBinding = ((BasePrimitiveBinding)binding).myBinding; + if (referencedBinding instanceof BeanBinding) { + Class referencedBeanClass = ((BeanBinding)referencedBinding).myBeanClass; + ThreeState compareByFields; + if (hasEqualMethod == null) { + compareByFields = null; + hasEqualMethod = new THashMap, ThreeState>(); + } + else { + compareByFields = hasEqualMethod.get(referencedBeanClass); + } + + if (compareByFields == null) { + try { + referencedBeanClass.getDeclaredMethod("equals", Object.class); + compareByFields = ThreeState.NO; + hasEqualMethod.put(referencedBeanClass, compareByFields); + } + catch (NoSuchMethodException ignored) { + compareByFields = ThreeState.YES; + hasEqualMethod.put(referencedBeanClass, compareByFields); + } + catch (Exception e) { + BeanBinding.LOG.warn(e); + } + } + + if (compareByFields == ThreeState.YES) { + return ((BeanBinding)referencedBinding).equalByFields(currentValue, defaultValue, this); + } + } + } + + return Comparing.equal(currentValue, defaultValue); + } + } +} diff --git a/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java b/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java index f254f451fcd1..c3af4340bf41 100644 --- a/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java +++ b/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,6 @@ import com.intellij.util.ThreeState; import gnu.trove.TObjectFloatHashMap; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.LinkedHashSet; @@ -40,11 +39,11 @@ public final class SmartSerializer { } : new SkipDefaultValuesSerializationFilters() { @Override - protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { if (mySerializedAccessorNameTracker != null && mySerializedAccessorNameTracker.contains(accessor.getName())) { return true; } - return super.accepts(accessor, bean, beanValue); + return super.accepts(accessor, bean); } }; } diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java index 97e4a35276a5..41a3e86a5a43 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -31,7 +31,7 @@ import java.util.Set; public class XmlSerializer { private static final SerializationFilter TRUE_FILTER = new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return true; } }; diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index d518b9c5828a..c2108d320ea8 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -158,6 +158,13 @@ public class XmlSerializerTest extends TestCase { bean); } + public void testSubBeanSerializationAndSkipDefaults() { + BeanWithSubBean bean = new BeanWithSubBean(); + doSerializerTest( + "", + bean, new SkipDefaultsSerializationFilter()); + } + public void testNullFieldValue() { BeanWithPublicFields bean1 = new BeanWithPublicFields(); @@ -538,7 +545,7 @@ public class XmlSerializerTest extends TestCase { "", new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accessor.getName().startsWith("I"); } }); @@ -851,7 +858,7 @@ public class XmlSerializerTest extends TestCase { } public static class PropertyFilterTest implements SerializationFilter { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return !accessor.read(bean).equals("skip"); } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java index ec4d81f86d2c..5dabf0b91e3b 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerBreakpointsContextProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -56,7 +56,7 @@ public class XDebuggerBreakpointsContextProvider extends WorkingContextProvider XBreakpointManagerImpl.BreakpointManagerState state = myBreakpointManager.getState(); Element serialize = XmlSerializer.serialize(state, new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accessor.read(bean) != null; } }); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java index 2b39f86d30b8..12fddd63d7f8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/XDebuggerWatchesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -54,7 +54,7 @@ public class XDebuggerWatchesProvider extends WorkingContextProvider { XDebuggerWatchesManager.WatchesManagerState state = myWatchesManager.getState(); Element serialize = XmlSerializer.serialize(state, new SerializationFilter() { @Override - public boolean accepts(@NotNull Accessor accessor, Object bean) { + public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) { return accessor.read(bean) != null; } }); From 0f17e9cbe80f3b0aed1d96e697966e9beef12fe7 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 16:25:44 +0100 Subject: [PATCH 171/231] cleanup --- .../util/src/com/intellij/util/xmlb/Accessor.java | 9 +-------- .../src/com/intellij/util/xmlb/FieldAccessor.java | 6 ------ .../com/intellij/util/xmlb/PropertyAccessor.java | 14 +------------- 3 files changed, 2 insertions(+), 27 deletions(-) diff --git a/platform/util/src/com/intellij/util/xmlb/Accessor.java b/platform/util/src/com/intellij/util/xmlb/Accessor.java index 7e364b9b6105..90cedb02a8d5 100644 --- a/platform/util/src/com/intellij/util/xmlb/Accessor.java +++ b/platform/util/src/com/intellij/util/xmlb/Accessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,13 +25,6 @@ public interface Accessor { void write(Object o, Object value); - @Deprecated - @NotNull - /** - * @deprecated to remove in IDEA 15 - */ - Annotation[] getAnnotations(); - T getAnnotation(@NotNull Class annotationClass); String getName(); diff --git a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java index fdb1eab69768..f2b0987aa0ca 100644 --- a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java @@ -55,12 +55,6 @@ class FieldAccessor implements Accessor { } } - @NotNull - @Override - public Annotation[] getAnnotations() { - return myField.getAnnotations(); - } - @Override public T getAnnotation(@NotNull Class annotationClass) { return myField.getAnnotation(annotationClass); diff --git a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java index 9780e683154d..3385dbc435ce 100644 --- a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -16,8 +16,6 @@ package com.intellij.util.xmlb; -import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -26,7 +24,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.List; class PropertyAccessor implements Accessor { private final String myName; @@ -80,15 +77,6 @@ class PropertyAccessor implements Accessor { } } - @Override - @NotNull - public Annotation[] getAnnotations() { - List result = new SmartList(); - ContainerUtil.addAll(result, myReadMethod.getAnnotations()); - ContainerUtil.addAll(result, myWriteMethod.getAnnotations()); - return result.toArray(new Annotation[result.size()]); - } - @Override public T getAnnotation(@NotNull Class annotationClass) { T annotation = myReadMethod.getAnnotation(annotationClass); From 74760875fbd3a14a24c86a4125f058bf1014ba2f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 23 Feb 2015 16:36:06 +0100 Subject: [PATCH 172/231] cleanup --- .../components/impl/stores/DefaultProjectStoreImpl.java | 3 ++- .../openapi/components/impl/stores/FileBasedStorage.java | 3 ++- .../openapi/components/impl/stores/XmlElementStorage.java | 1 + .../openapi/components/impl/XmlElementStorageTest.java | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 2b755dbde9ca..5d7cd510c347 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -58,6 +58,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { return getStateCopy(); } + @NotNull @Override protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) { return new XmlElementStorageSaveSession(storageData) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java index 6142c0823986..1fdc5718aeb8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java @@ -94,6 +94,7 @@ public class FileBasedStorage extends XmlElementStorage { return isUseXmlProlog(); } + @NotNull @Override protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) { return new FileSaveSession(storageData); @@ -106,7 +107,7 @@ public class FileBasedStorage extends XmlElementStorage { } } - private class FileSaveSession extends XmlElementStorageSaveSession { + private class FileSaveSession extends XmlElementStorageSaveSession { protected FileSaveSession(@NotNull StorageData storageData) { super(storageData); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index 78b624949979..f1f7f1e308e8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -130,6 +130,7 @@ public abstract class XmlElementStorage extends StateStorageBase { return checkIsSavingDisabled() ? null : createSaveSession(getStorageData()); } + @NotNull protected abstract XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData); @Nullable diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java index 34f6874b9da9..0fafc897cdad 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -94,6 +94,7 @@ public class XmlElementStorageTest extends LightPlatformLangTestCase { return myElement; } + @NotNull @Override protected XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData) { return new XmlElementStorageSaveSession(storageData) { From 01077fc7e2367160cc1c429af43087d0b440c79d Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 07:22:41 +0100 Subject: [PATCH 173/231] cache hasEqualMethod in BeanBinding --- .../com/intellij/util/xmlb/BeanBinding.java | 3 +++ .../xmlb/SkipDefaultsSerializationFilter.java | 27 +++++-------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index ad15638fff36..3995cafbc9f1 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ReflectionUtil; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.MultiMap; @@ -49,6 +50,8 @@ class BeanBinding extends Binding { final Class myBeanClass; + ThreeState hasEqualMethod = ThreeState.UNSURE; + public BeanBinding(@NotNull Class beanClass, @Nullable Accessor accessor) { super(accessor); diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java index f138b621e2ad..5d43f7c01d49 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultsSerializationFilter.java @@ -18,16 +18,11 @@ package com.intellij.util.xmlb; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.JDOMUtil; import com.intellij.util.ThreeState; -import gnu.trove.THashMap; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; - public final class SkipDefaultsSerializationFilter extends SkipDefaultValuesSerializationFilters { - private Map, ThreeState> hasEqualMethod; - boolean equal(@NotNull Binding binding, @NotNull Object bean) { Accessor accessor = binding.getAccessor(); return equal(binding, accessor.read(bean), accessor.read(getDefaultBean(bean))); @@ -48,33 +43,25 @@ public final class SkipDefaultsSerializationFilter extends SkipDefaultValuesSeri if (binding instanceof BasePrimitiveBinding) { Binding referencedBinding = ((BasePrimitiveBinding)binding).myBinding; if (referencedBinding instanceof BeanBinding) { - Class referencedBeanClass = ((BeanBinding)referencedBinding).myBeanClass; - ThreeState compareByFields; - if (hasEqualMethod == null) { - compareByFields = null; - hasEqualMethod = new THashMap, ThreeState>(); - } - else { - compareByFields = hasEqualMethod.get(referencedBeanClass); - } - - if (compareByFields == null) { + BeanBinding classBinding = (BeanBinding)referencedBinding; + ThreeState compareByFields = classBinding.hasEqualMethod; + if (compareByFields == ThreeState.UNSURE) { try { - referencedBeanClass.getDeclaredMethod("equals", Object.class); + classBinding.myBeanClass.getDeclaredMethod("equals", Object.class); compareByFields = ThreeState.NO; - hasEqualMethod.put(referencedBeanClass, compareByFields); } catch (NoSuchMethodException ignored) { compareByFields = ThreeState.YES; - hasEqualMethod.put(referencedBeanClass, compareByFields); } catch (Exception e) { BeanBinding.LOG.warn(e); } + + classBinding.hasEqualMethod = compareByFields; } if (compareByFields == ThreeState.YES) { - return ((BeanBinding)referencedBinding).equalByFields(currentValue, defaultValue, this); + return classBinding.equalByFields(currentValue, defaultValue, this); } } } From 6ca4b6b883c1f8dd1ac4379f41aac73afcb3e461 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 24 Feb 2015 10:35:09 +0300 Subject: [PATCH 174/231] IDEA-136798 Switching between editors does not restore scroll position properly when soft-wraps are involved --- .../com/intellij/openapi/editor/impl/SoftWrapModelImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index d39877081825..e234be4f0b2a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -185,6 +185,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi if ((myUseSoftWraps ^ softWrapsUsedBefore) || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore) || fontsChanged) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); + myStorage.removeAll(); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } } @@ -286,9 +287,6 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi * @return total number of soft wrap-introduced new visual lines */ public int getSoftWrapsIntroducedLinesNumber() { - if (!isSoftWrappingEnabled()) { - return 0; - } return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time } From dfc658ce1867ecd58d67281f2f0c69f6d6376434 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 07:33:09 +0100 Subject: [PATCH 175/231] use SkipDefaultsSerializationFilter in tests --- .../testSrc/com/intellij/util/xmlb/XmlSerializerTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index c2108d320ea8..d318dc2f8cd4 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -1202,10 +1202,10 @@ public class XmlSerializerTest extends TestCase { public void testConverterUsingSkipDefaultsFilters() { BeanWithConverter bean = new BeanWithConverter(); - doSerializerTest("", bean, new SkipDefaultValuesSerializationFilters()); + doSerializerTest("", bean, new SkipDefaultsSerializationFilter()); bean.foo = Ref.create("testValue"); - doSerializerTest("", bean, new SkipDefaultValuesSerializationFilters()); + doSerializerTest("", bean, new SkipDefaultsSerializationFilter()); bean.foo = Ref.create(); bean.bar = Ref.create("testValue2"); @@ -1244,7 +1244,7 @@ public class XmlSerializerTest extends TestCase { Bean2 bean = new Bean2(); bean.module = "module"; bean.ab = "ab"; - doSerializerTest("", bean, new SkipDefaultValuesSerializationFilters()); + doSerializerTest("", bean, new SkipDefaultsSerializationFilter()); checkSmartSerialization(new Bean2(), ""); checkSmartSerialization(new Bean2(), ""); @@ -1271,7 +1271,7 @@ public class XmlSerializerTest extends TestCase { " \n" + " \n" + " \n" + - "", bean, new SkipDefaultValuesSerializationFilters()); + "", bean, new SkipDefaultsSerializationFilter()); } private static void checkSmartSerialization(@NotNull Bean2 bean, @NotNull String serialized) throws IOException, JDOMException { From c212341aae530be59a07f4a3f4b46ecd559b61f8 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 09:40:50 +0100 Subject: [PATCH 176/231] ExternalResourceManagerImpl must not save defaults (standard ignored resources) --- .../idea/maven/dom/MavenSchemaProvider.java | 7 +- .../ExternalResourcesRootsProvider.java | 18 +- .../javaee/ExternalResourceManager.java | 33 +-- .../javaee/CoreExternalResourceManager.java | 26 +-- .../javaee/ExternalResourceManagerEx.java | 21 +- .../javaee/ExternalResourceManagerExImpl.java | 214 ++++++++++-------- .../com/intellij/javaee/ProjectResources.java | 4 +- .../javaee/ResourceRegistrarImpl.java | 13 +- 8 files changed, 186 insertions(+), 150 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java index 26df2720e259..f3bcf765e5f5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenSchemaProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,7 @@ import com.intellij.javaee.ExternalResourceManager; import com.intellij.javaee.ExternalResourceManagerEx; import com.intellij.javaee.ResourceRegistrar; import com.intellij.javaee.StandardResourceProvider; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -28,6 +28,7 @@ public class MavenSchemaProvider implements StandardResourceProvider { public static final String MAVEN_PROFILES_SCHEMA_URL = "http://maven.apache.org/xsd/profiles-1.0.0.xsd"; public static final String MAVEN_SETTINGS_SCHEMA_URL = "http://maven.apache.org/xsd/settings-1.0.0.xsd"; + @Override public void registerResources(ResourceRegistrar registrar) { registrar.addStdResource("http://maven.apache.org/maven-v4_0_0.xsd", "/schemas/maven-4.0.0.xsd", getClass()); registrar.addStdResource(MAVEN_PROJECT_SCHEMA_URL, "/schemas/maven-4.0.0.xsd", getClass()); @@ -41,7 +42,7 @@ public class MavenSchemaProvider implements StandardResourceProvider { String location = ((ExternalResourceManagerEx)ExternalResourceManager.getInstance()).getStdResource(url, null); assert location != null : "cannot find a standard resource for " + url; - VirtualFile result = VfsUtil.findRelativeFile(location, null); + VirtualFile result = VfsUtilCore.findRelativeFile(location, null); assert result != null : "cannot find a schema file for URL: " + url + " location: " + location; return result; diff --git a/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java b/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java index f629e3216c03..795feb38fec3 100644 --- a/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java +++ b/xml/impl/src/com/intellij/javaee/ExternalResourcesRootsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,10 +22,9 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.IndexableSetContributor; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -33,16 +32,14 @@ import java.util.Set; * @author Dmitry Avdeev */ public class ExternalResourcesRootsProvider extends IndexableSetContributor { - private final NotNullLazyValue> myStandardResources = new NotNullLazyValue>() { @NotNull @Override protected Set compute() { ExternalResourceManagerExImpl manager = (ExternalResourceManagerExImpl)ExternalResourceManager.getInstance(); - Collection> resources = manager.getStandardResources(); - Set dirs = new HashSet(); - Set set = new HashSet(); - for (Map map : resources) { + Set dirs = new THashSet(); + Set set = new THashSet(); + for (Map map : manager.getStandardResources()) { for (ExternalResourceManagerExImpl.Resource resource : map.values()) { ExternalResourceManagerExImpl.Resource dir = new ExternalResourceManagerExImpl.Resource( resource.directoryName(), resource); @@ -61,8 +58,7 @@ public class ExternalResourcesRootsProvider extends IndexableSetContributor { @Override public Set getAdditionalRootsToIndex() { - - HashSet roots = new HashSet(); + Set roots = new THashSet(); for (String url : myStandardResources.getValue()) { VirtualFile file = VfsUtilCore.findRelativeFile(url, null); if (file != null) { @@ -73,7 +69,7 @@ public class ExternalResourcesRootsProvider extends IndexableSetContributor { String path = FetchExtResourceAction.getExternalResourcesPath(); VirtualFile extResources = LocalFileSystem.getInstance().findFileByPath(path); ContainerUtil.addIfNotNull(extResources, roots); - + return roots; } } diff --git a/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java b/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java index fb8d7dfae5e9..05f7d7c037ca 100644 --- a/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java +++ b/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,30 +24,33 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * author: lesya - */ public abstract class ExternalResourceManager extends SimpleModificationTracker { public static ExternalResourceManager getInstance() { return ServiceManager.getService(ExternalResourceManager.class); } - public abstract void addResource(@NonNls String url, @NonNls String location); - public abstract void addResource(@NonNls String url, @NonNls String version, @NonNls String location); + public abstract void addResource(@NotNull @NonNls String url, @NonNls String location); - public abstract void removeResource(String url); - public abstract void removeResource(String url, String version); + public abstract void addResource(@NotNull @NonNls String url, @NonNls @Nullable String version, @NonNls String location); - /** @see #getResourceLocation(String, com.intellij.openapi.project.Project) */ + public abstract void removeResource(@NotNull String url); + + public abstract void removeResource(@NotNull String url, @Nullable String version); + + /** + * @see #getResourceLocation(String, com.intellij.openapi.project.Project) + */ @Deprecated - public abstract String getResourceLocation(@NonNls String url); - public abstract String getResourceLocation(@NonNls String url, String version); + public abstract String getResourceLocation(@NotNull @NonNls String url); - public abstract String getResourceLocation(@NonNls String url, @NotNull Project project); + public abstract String getResourceLocation(@NotNull @NonNls String url, @Nullable String version); + + public abstract String getResourceLocation(@NotNull @NonNls String url, @NotNull Project project); @Nullable - public abstract PsiFile getResourceLocation(@NotNull @NonNls String url, @NotNull PsiFile baseFile, String version); + public abstract PsiFile getResourceLocation(@NotNull @NonNls String url, @NotNull PsiFile baseFile, @Nullable String version); - public abstract String[] getResourceUrls(@Nullable FileType fileType, final boolean includeStandard); - public abstract String[] getResourceUrls(@Nullable FileType fileType, @NonNls String version, final boolean includeStandard); + public abstract String[] getResourceUrls(@Nullable FileType fileType, boolean includeStandard); + + public abstract String[] getResourceUrls(@Nullable FileType fileType, @NonNls @Nullable String version, boolean includeStandard); } diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/CoreExternalResourceManager.java b/xml/xml-psi-impl/src/com/intellij/javaee/CoreExternalResourceManager.java index 8e2202c697b4..c3ebfe17f070 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/CoreExternalResourceManager.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/CoreExternalResourceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -56,17 +56,17 @@ public class CoreExternalResourceManager extends ExternalResourceManagerEx { } @Override - public void addIgnoredResource(String url) { + public void addIgnoredResource(@NotNull String url) { throw new UnsupportedOperationException(); } @Override - public void removeIgnoredResource(String url) { + public void removeIgnoredResource(@NotNull String url) { throw new UnsupportedOperationException(); } @Override - public boolean isIgnoredResource(String url) { + public boolean isIgnoredResource(@NotNull String url) { return false; } @@ -103,7 +103,7 @@ public class CoreExternalResourceManager extends ExternalResourceManagerEx { @Nullable @Override - public String getStdResource(String url, String version) { + public String getStdResource(@NotNull String url, @Nullable String version) { throw new UnsupportedOperationException(); } @@ -134,37 +134,37 @@ public class CoreExternalResourceManager extends ExternalResourceManagerEx { } @Override - public void addResource(@NonNls String url, @NonNls String location) { + public void addResource(@NotNull @NonNls String url, @NonNls String location) { throw new UnsupportedOperationException(); } @Override - public void addResource(@NonNls String url, @NonNls String version, @NonNls String location) { + public void addResource(@NotNull @NonNls String url, @NonNls String version, @NonNls String location) { throw new UnsupportedOperationException(); } @Override - public void removeResource(String url) { + public void removeResource(@NotNull String url) { throw new UnsupportedOperationException(); } @Override - public void removeResource(String url, String version) { + public void removeResource(@NotNull String url, @Nullable String version) { throw new UnsupportedOperationException(); } @Override - public String getResourceLocation(@NonNls String url) { + public String getResourceLocation(@NotNull @NonNls String url) { throw new UnsupportedOperationException(); } @Override - public String getResourceLocation(@NonNls String url, String version) { + public String getResourceLocation(@NotNull @NonNls String url, @Nullable String version) { throw new UnsupportedOperationException(); } @Override - public String getResourceLocation(@NonNls String url, @NotNull Project project) { + public String getResourceLocation(@NotNull @NonNls String url, @NotNull Project project) { throw new UnsupportedOperationException(); } @@ -180,7 +180,7 @@ public class CoreExternalResourceManager extends ExternalResourceManagerEx { } @Override - public String[] getResourceUrls(@Nullable FileType fileType, @NonNls String version, boolean includeStandard) { + public String[] getResourceUrls(@Nullable FileType fileType, @NotNull @NonNls String version, boolean includeStandard) { throw new UnsupportedOperationException(); } } diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerEx.java b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerEx.java index 1432ea35365b..e8b7ee614536 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerEx.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,13 +21,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * author: lesya - */ public abstract class ExternalResourceManagerEx extends ExternalResourceManager { @NonNls public static final String STANDARD_SCHEMAS = "/standardSchemas/"; - public static ExternalResourceManagerEx getInstanceEx(){ + public static ExternalResourceManagerEx getInstanceEx() { return (ExternalResourceManagerEx)getInstance(); } @@ -36,15 +33,18 @@ public abstract class ExternalResourceManagerEx extends ExternalResourceManager public abstract void addResource(@NonNls String url, @NonNls String location, @NotNull Project project); public abstract String[] getAvailableUrls(); + public abstract String[] getAvailableUrls(Project project); public abstract void clearAllResources(); + public abstract void clearAllResources(Project project); - public abstract void addIgnoredResource(String url); - public abstract void removeIgnoredResource(String url); + public abstract void addIgnoredResource(@NotNull String url); - public abstract boolean isIgnoredResource(String url); + public abstract void removeIgnoredResource(@NotNull String url); + + public abstract boolean isIgnoredResource(@NotNull String url); public abstract String[] getIgnoredResources(); @@ -53,12 +53,14 @@ public abstract class ExternalResourceManagerEx extends ExternalResourceManager public abstract void removeExternalResourceListener(ExternalResourceListener listener); public abstract boolean isUserResource(VirtualFile file); + public abstract boolean isStandardResource(VirtualFile file); @Nullable public abstract String getUserResource(Project project, String url, String version); + @Nullable - public abstract String getStdResource(String url, String version); + public abstract String getStdResource(@NotNull String url, @Nullable String version); @NotNull public abstract String getDefaultHtmlDoctype(@NotNull Project project); @@ -66,6 +68,7 @@ public abstract class ExternalResourceManagerEx extends ExternalResourceManager public abstract void setDefaultHtmlDoctype(@NotNull String defaultHtmlDoctype, @NotNull Project project); public abstract String getCatalogPropertiesFile(); + public abstract void setCatalogPropertiesFile(@Nullable String filePath); public abstract long getModificationCount(@NotNull Project project); diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java index a9a1980f80bc..93829e962d63 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,23 +21,21 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.AtomicNotNullLazyValue; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.NotNullLazyKey; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlFile; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.HashMap; import com.intellij.xml.Html5SchemaProvider; import com.intellij.xml.XmlSchemaProvider; import com.intellij.xml.util.XmlUtil; +import gnu.trove.THashMap; +import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -61,12 +59,13 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @NonNls public static final String JAVAEE_NS = "http://java.sun.com/xml/ns/javaee/"; private static final String CATALOG_PROPERTIES_ELEMENT = "CATALOG_PROPERTIES"; - private final Map> myResources = new HashMap>(); - private final Set myResourceLocations = new HashSet(); + private final Map> myResources = new THashMap>(); + private final Set myResourceLocations = new THashSet(); - private final Set myIgnoredResources = new HashSet(); + private final Set myIgnoredResources = new TreeSet(); + private final Set myStandardIgnoredResources = new TreeSet(); - private final AtomicNotNullLazyValue>> myStdResources = new AtomicNotNullLazyValue>>() { + private final NotNullLazyValue>> myStandardResources = new AtomicNotNullLazyValue>>() { @NotNull @Override protected Map> compute() { @@ -82,15 +81,14 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp protected Map> computeStdResources() { ResourceRegistrarImpl registrar = new ResourceRegistrarImpl(); - for (StandardResourceProvider provider : Extensions.getExtensions(StandardResourceProvider.EP_NAME)) { + for (StandardResourceProvider provider : StandardResourceProvider.EP_NAME.getExtensions()) { provider.registerResources(registrar); } - StandardResourceEP[] extensions = Extensions.getExtensions(StandardResourceEP.EP_NAME); - for (StandardResourceEP extension : extensions) { + for (StandardResourceEP extension : StandardResourceEP.EP_NAME.getExtensions()) { registrar.addStdResource(extension.url, extension.version, extension.resourcePath, null, extension.getLoaderForClass()); } - myIgnoredResources.addAll(registrar.getIgnored()); + myStandardIgnoredResources.addAll(registrar.getIgnored()); return registrar.getResources(); } @@ -100,7 +98,8 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @NonNls private static final String LOCATION_ATTR = "location"; @NonNls private static final String IGNORED_RESOURCE_ELEMENT = "ignored-resource"; @NonNls private static final String HTML_DEFAULT_DOCTYPE_ELEMENT = "default-html-doctype"; - private static final String DEFAULT_VERSION = null; + + private static final String DEFAULT_VERSION = ""; @Override public boolean isStandardResource(VirtualFile file) { @@ -114,42 +113,41 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Nullable - static Map getMap(@NotNull final Map> resources, - @Nullable final String version, - final boolean create) { + static Map getMap(@NotNull Map> resources, @Nullable String version, boolean create) { + version = StringUtil.notNullize(version, DEFAULT_VERSION); Map map = resources.get(version); if (map == null) { if (create) { - map = ContainerUtil.newHashMap(); + map = new THashMap(); resources.put(version, map); } - else if (version == null || !version.equals(DEFAULT_VERSION)) { + else if (!version.equals(DEFAULT_VERSION)) { map = resources.get(DEFAULT_VERSION); } } - return map; } @Override - public String getResourceLocation(String url) { + public String getResourceLocation(@NotNull String url) { return getResourceLocation(url, DEFAULT_VERSION); } @Override - public String getResourceLocation(@NonNls String url, String version) { - String result = getUserResource(url, version); + public String getResourceLocation(@NotNull @NonNls String url, @Nullable String version) { + String result = getUserResource(url, StringUtil.notNullize(version, DEFAULT_VERSION)); if (result == null) { XMLCatalogManager manager = getCatalogManager(); if (manager != null) { result = manager.resolve(url); } - } - if (result == null) { - result = getStdResource(url, version); - } - if (result == null) { - result = url; + + if (result == null) { + result = getStdResource(url, version); + if (result == null) { + return url; + } + } } return result; } @@ -163,8 +161,8 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @Override @Nullable - public String getStdResource(String url, String version) { - Map map = getMap(myStdResources.getValue(), version, false); + public String getStdResource(@NotNull String url, @Nullable String version) { + Map map = getMap(myStandardResources.getValue(), version, false); if (map != null) { Resource resource = map.get(url); return resource == null ? null : resource.getResourceUrl(); @@ -175,13 +173,13 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Nullable - private String getUserResource(String url, String version) { + private String getUserResource(@NotNull String url, @Nullable String version) { Map map = getMap(myResources, version, false); return map != null ? map.get(url) : null; } @Override - public String getResourceLocation(@NonNls String url, @NotNull Project project) { + public String getResourceLocation(@NotNull @NonNls String url, @NotNull Project project) { String location = getProjectResources(project).getResourceLocation(url); return location == null || location.equals(url) ? getResourceLocation(url) : location; } @@ -203,28 +201,27 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public String[] getResourceUrls(FileType fileType, final boolean includeStandard) { + public String[] getResourceUrls(FileType fileType, boolean includeStandard) { return getResourceUrls(fileType, DEFAULT_VERSION, includeStandard); } @Override - public String[] getResourceUrls(@Nullable final FileType fileType, @NonNls final String version, final boolean includeStandard) { - final List result = new LinkedList(); + public String[] getResourceUrls(@Nullable FileType fileType, @Nullable @NonNls String version, boolean includeStandard) { + List result = new LinkedList(); addResourcesFromMap(result, version, myResources); if (includeStandard) { - addResourcesFromMap(result, version, myStdResources.getValue()); + addResourcesFromMap(result, version, myStandardResources.getValue()); } return ArrayUtil.toStringArray(result); } - private static void addResourcesFromMap(final List result, - String version, - Map> resourcesMap) { + private static void addResourcesFromMap(@NotNull List result, @Nullable String version, @NotNull Map> resourcesMap) { Map resources = getMap(resourcesMap, version, false); - if (resources == null) return; - result.addAll(resources.keySet()); + if (resources != null) { + result.addAll(resources.keySet()); + } } @TestOnly @@ -249,19 +246,19 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp }); } @Override - public void addResource(String url, String location) { + public void addResource(@NotNull String url, String location) { addResource(url, DEFAULT_VERSION, location); } @Override - public void addResource(@NonNls String url, @NonNls String version, @NonNls String location) { + public void addResource(@NotNull @NonNls String url, @NonNls String version, @NonNls String location) { ApplicationManager.getApplication().assertWriteAccessAllowed(); addSilently(url, version, location); fireExternalResourceChanged(); } - private void addSilently(String url, String version, String location) { - final Map map = getMap(myResources, version, true); + private void addSilently(@NotNull String url, @Nullable String version, String location) { + Map map = getMap(myResources, version, true); assert map != null; map.put(url, location); myResourceLocations.add(location); @@ -269,12 +266,12 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public void removeResource(String url) { + public void removeResource(@NotNull String url) { removeResource(url, DEFAULT_VERSION); } @Override - public void removeResource(String url, String version) { + public void removeResource(@NotNull String url, @Nullable String version) { ApplicationManager.getApplication().assertWriteAccessAllowed(); Map map = getMap(myResources, version, false); if (map != null) { @@ -299,7 +296,7 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp @Override public String[] getAvailableUrls() { - Set urls = new HashSet(); + Set urls = new THashSet(); for (Map map : myResources.values()) { urls.addAll(map.keySet()); } @@ -327,19 +324,29 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public void addIgnoredResource(String url) { + public void addIgnoredResource(@NotNull String url) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - addIgnoredSilently(url); - fireExternalResourceChanged(); + if (addIgnoredSilently(url)) { + fireExternalResourceChanged(); + } } - private void addIgnoredSilently(String url) { - myIgnoredResources.add(url); - incModificationCount(); + private boolean addIgnoredSilently(@NotNull String url) { + if (myStandardIgnoredResources.contains(url)) { + return false; + } + + if (myIgnoredResources.add(url)) { + incModificationCount(); + return true; + } + else { + return false; + } } @Override - public void removeIgnoredResource(String url) { + public void removeIgnoredResource(@NotNull String url) { ApplicationManager.getApplication().assertWriteAccessAllowed(); if (myIgnoredResources.remove(url)) { incModificationCount(); @@ -348,23 +355,38 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } @Override - public boolean isIgnoredResource(String url) { - myStdResources.getValue(); // ensure ignored resources are loaded - return myIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url); + public boolean isIgnoredResource(@NotNull String url) { + if (myIgnoredResources.contains(url)) { + return true; + } + + // ensure ignored resources are loaded + myStandardResources.getValue(); + return myStandardIgnoredResources.contains(url) || isImplicitNamespaceDescriptor(url); } - private static boolean isImplicitNamespaceDescriptor(String url) { - for (ImplicitNamespaceDescriptorProvider namespaceDescriptorProvider : Extensions - .getExtensions(ImplicitNamespaceDescriptorProvider.EP_NAME)) { - if (namespaceDescriptorProvider.getNamespaceDescriptor(null, url, null) != null) return true; + private static boolean isImplicitNamespaceDescriptor(@NotNull String url) { + for (ImplicitNamespaceDescriptorProvider provider : ImplicitNamespaceDescriptorProvider.EP_NAME.getExtensions()) { + if (provider.getNamespaceDescriptor(null, url, null) != null) { + return true; + } } return false; } @Override public String[] getIgnoredResources() { - myStdResources.getValue(); // ensure ignored resources are loaded - return ArrayUtil.toStringArray(myIgnoredResources); + // ensure ignored resources are loaded + myStandardResources.getValue(); + + if (myIgnoredResources.isEmpty()) { + return ArrayUtil.toStringArray(myStandardIgnoredResources); + } + + Set set = new THashSet(myIgnoredResources.size() + myStandardIgnoredResources.size()); + set.addAll(myIgnoredResources); + set.addAll(myStandardIgnoredResources); + return ArrayUtil.toStringArray(set); } @Override @@ -372,25 +394,34 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp return getProjectResources(project).getModificationCount(); } - @Nullable @Override public Element getState() { Element element = new Element("state"); - final String[] urls = getAvailableUrls(); - for (String url : urls) { - if (url == null) continue; - String location = getResourceLocation(url); - if (location == null) continue; - final Element e = new Element(RESOURCE_ELEMENT); + Set urls = new TreeSet(); + for (Map map : myResources.values()) { + urls.addAll(map.keySet()); + } + + for (String url : urls) { + if (url == null) { + continue; + } + + String location = getResourceLocation(url); + if (location == null) { + continue; + } + + Element e = new Element(RESOURCE_ELEMENT); e.setAttribute(URL_ATTR, url); e.setAttribute(LOCATION_ATTR, location.replace(File.separatorChar, '/')); element.addContent(e); } - final String[] ignoredResources = getIgnoredResources(); - for (String ignoredResource : ignoredResources) { + myIgnoredResources.removeAll(myStandardIgnoredResources); + for (String ignoredResource : myIgnoredResources) { Element e = new Element(IGNORED_RESOURCE_ELEMENT); e.setAttribute(URL_ATTR, ignoredResource); element.addContent(e); @@ -406,30 +437,33 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp properties.setText(myCatalogPropertiesFile); element.addContent(properties); } - final ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap(); + + ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap(); PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements); macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive); return element; } @Override - public void loadState(Element element) { - final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap(); + public void loadState(Element state) { + ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap(); PathMacrosImpl.getInstanceEx().addMacroExpands(macroExpands); - macroExpands.substitute(element, SystemInfo.isFileSystemCaseSensitive); + macroExpands.substitute(state, SystemInfo.isFileSystemCaseSensitive); incModificationCount(); - for (final Object o1 : element.getChildren(RESOURCE_ELEMENT)) { - Element e = (Element)o1; - addSilently(e.getAttributeValue(URL_ATTR), DEFAULT_VERSION, e.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar)); + for (Element element : state.getChildren(RESOURCE_ELEMENT)) { + String url = element.getAttributeValue(URL_ATTR); + if (!StringUtil.isEmpty(url)) { + addSilently(url, DEFAULT_VERSION, element.getAttributeValue(LOCATION_ATTR).replace('/', File.separatorChar)); + } } - for (final Object o : element.getChildren(IGNORED_RESOURCE_ELEMENT)) { - Element e = (Element)o; - addIgnoredSilently(e.getAttributeValue(URL_ATTR)); + myIgnoredResources.clear(); + for (Element element : state.getChildren(IGNORED_RESOURCE_ELEMENT)) { + addIgnoredSilently(element.getAttributeValue(URL_ATTR)); } - Element child = element.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT); + Element child = state.getChild(HTML_DEFAULT_DOCTYPE_ELEMENT); if (child != null) { String text = child.getText(); if (FileUtil.toSystemIndependentName(text).endsWith(".jar!/resources/html5-schema/html5.rnc")) { @@ -437,13 +471,12 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } myDefaultHtmlDoctype = text; } - Element catalogElement = element.getChild(CATALOG_PROPERTIES_ELEMENT); + Element catalogElement = state.getChild(CATALOG_PROPERTIES_ELEMENT); if (catalogElement != null) { myCatalogPropertiesFile = catalogElement.getTextTrim(); } } - @Override public void addExternalResourceListener(ExternalResourceListener listener) { myListeners.add(listener); @@ -461,10 +494,9 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx imp } Collection> getStandardResources() { - return myStdResources.getValue().values(); + return myStandardResources.getValue().values(); } - private static final NotNullLazyKey INSTANCE_CACHE = ServiceManager.createLazyKey(ExternalResourceManagerExImpl.class); private static ExternalResourceManagerExImpl getProjectResources(Project project) { diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java b/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java index 4b9541b0ebe2..7f4a69b1847a 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/ProjectResources.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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.javaee; -import com.intellij.application.options.PathMacrosImpl; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; @@ -29,6 +28,7 @@ import java.util.Map; */ @State(name = "ProjectResources", storages = {@Storage(file = StoragePathMacros.PROJECT_FILE)}) public class ProjectResources extends ExternalResourceManagerExImpl { + @NotNull @Override protected Map> computeStdResources() { return Collections.emptyMap(); diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java b/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java index a0fa57929f14..37462e2410b1 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/ResourceRegistrarImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.javaee; -import com.intellij.util.containers.HashMap; +import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -28,8 +28,7 @@ import java.util.Map; * @author Dmitry Avdeev */ public class ResourceRegistrarImpl implements ResourceRegistrar { - - private final Map> myResources = new HashMap>(); + private final Map> myResources = new THashMap>(); private final List myIgnored = new ArrayList(); @Override @@ -43,7 +42,7 @@ public class ResourceRegistrarImpl implements ResourceRegistrar { } public void addStdResource(@NonNls String resource, @NonNls String version, @NonNls String fileName, @Nullable Class klass, @Nullable ClassLoader classLoader) { - final Map map = ExternalResourceManagerExImpl.getMap(myResources, version, true); + Map map = ExternalResourceManagerExImpl.getMap(myResources, version, true); assert map != null; resource = new String(resource); // enforce copying; todo remove after final migration to JDK 1.7 map.put(resource, new ExternalResourceManagerExImpl.Resource(fileName, klass, classLoader)); @@ -75,10 +74,12 @@ public class ResourceRegistrarImpl implements ResourceRegistrar { addStdResource(resource, version, ExternalResourceManagerEx.STANDARD_SCHEMAS + fileName, clazz); } + @NotNull public Map> getResources() { return myResources; } + @NotNull public List getIgnored() { return myIgnored; } From 4d940106571a719717c9a23ddf610cb0734e5323 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 11:44:10 +0300 Subject: [PATCH 177/231] hunting for the blinking test --- .../daemon/XmlHighlightingTest.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java index e5932749068b..d88422df2127 100644 --- a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java +++ b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java @@ -57,11 +57,14 @@ import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.impl.include.FileIncludeManager; import com.intellij.psi.search.PsiElementProcessor; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.*; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; +import com.intellij.xml.XmlAttributeDescriptor; import com.intellij.xml.XmlBundle; +import com.intellij.xml.impl.schema.XmlElementDescriptorImpl; import com.intellij.xml.util.*; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -2062,16 +2065,19 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase { } public void testAnyAttributeNavigation() throws Exception { - doTest( - new VirtualFile[] { - getVirtualFile(BASE_PATH + "AnyAttributeNavigation/test.xml"), - getVirtualFile(BASE_PATH + "AnyAttributeNavigation/test.xsd"), - getVirtualFile(BASE_PATH + "AnyAttributeNavigation/library.xsd") - }, - true, - false - ); + configureByFiles(null, getVirtualFile(BASE_PATH + "AnyAttributeNavigation/test.xml"), + getVirtualFile(BASE_PATH + "AnyAttributeNavigation/test.xsd"), + getVirtualFile(BASE_PATH + "AnyAttributeNavigation/library.xsd")); + PsiReference at = getFile().findReferenceAt(getEditor().getCaretModel().getOffset()); + + XmlTag tag = PsiTreeUtil.getParentOfType(at.getElement(), XmlTag.class); + XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)tag.getDescriptor(); + XmlAttributeDescriptor[] descriptors = descriptor.getAttributesDescriptors(tag); + System.out.println(Arrays.asList(descriptors)); + + doDoTest(true, false); + PsiElement resolve = at.resolve(); assertTrue(resolve instanceof XmlTag); } From c99b8731ec7f9de0ed57b0a59f28102ea249094b Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Tue, 24 Feb 2015 00:18:43 +0300 Subject: [PATCH 178/231] OC-11340 parameterized resolving --- .../com/intellij/util/containers/MostlySingularMultiMap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java b/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java index cfe57a2aedaf..11e953de6dcf 100644 --- a/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java +++ b/platform/util/src/com/intellij/util/containers/MostlySingularMultiMap.java @@ -96,7 +96,7 @@ public class MostlySingularMultiMap implements Serializable { return processValue(p, myMap.get(key)); } - private boolean processValue(@NotNull Processor p, Object v) { + private boolean processValue(@NotNull Processor p, Object v) { if (v instanceof Object[]) { for (Object o : (Object[])v) { if (!p.process((V)o)) return false; @@ -109,7 +109,7 @@ public class MostlySingularMultiMap implements Serializable { return true; } - public boolean processAllValues(@NotNull Processor p) { + public boolean processAllValues(@NotNull Processor p) { for (Object v : myMap.values()) { if (!processValue(p, v)) return false; } From 1c4a2102d7d997326ddaec0e0cb21cfd8afc26a4 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 23 Feb 2015 08:57:55 +0100 Subject: [PATCH 179/231] make toggle soft wraps actions DumbAware --- .../editor/actions/AbstractToggleUseSoftWrapsAction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java index b5662c6ab49f..69e4f7b2991e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/AbstractToggleUseSoftWrapsAction.java @@ -17,12 +17,12 @@ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; +import com.intellij.openapi.project.DumbAware; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable; * @author Denis Zhdanov * @since Aug 23, 2010 11:33:35 AM */ -public abstract class AbstractToggleUseSoftWrapsAction extends ToggleAction { +public abstract class AbstractToggleUseSoftWrapsAction extends ToggleAction implements DumbAware { private final SoftWrapAppliancePlaces myAppliancePlace; private final boolean myGlobal; From a1f00bd5730a1a1371179fda9b2786ae2be0f8d8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Feb 2015 09:34:04 +0100 Subject: [PATCH 180/231] IDEA-136868 AE at com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix.invoke(IncreaseLanguageLevelFix.java:101) --- .../analysis/IncreaseLanguageLevelFix.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java index 87867565f63a..466903efaf30 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java @@ -86,20 +86,20 @@ public class IncreaseLanguageLevelFix implements IntentionAction { LOG.assertTrue(virtualFile != null); final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project); final LanguageLevel moduleLevel = module == null ? null : LanguageLevelModuleExtensionImpl.getInstance(module).getLanguageLevel(); - if (moduleLevel != null && isLanguageLevelAcceptable(project, module, myLevel)) { - final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel(); - rootModel.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLevel); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + if (moduleLevel != null && isLanguageLevelAcceptable(project, module, myLevel)) { + final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel(); + rootModel.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLevel); rootModel.commit(); } - }); - } - else { - LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(myLevel); - ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(EmptyRunnable.INSTANCE, false, true); - } + else { + LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(myLevel); + ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(EmptyRunnable.INSTANCE, false, true); + } + } + }); } @Nullable From 508344da8bbde65b1c951236d4f6da6035560237 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Tue, 24 Feb 2015 12:24:02 +0300 Subject: [PATCH 181/231] Do not ignore stored in document indent options when showing notification. In other case new calculated options can be different from used ones (IDEA-136752) --- .../autodetect/DetectedIndentOptionsNotificationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index aea68bf6d430..24d745373d4b 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -65,7 +65,7 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); CommonCodeStyleSettings.IndentOptions userOptions = settings.getIndentOptions(psiFile.getFileType()); CommonCodeStyleSettings.IndentOptions detectedOptions = CodeStyleSettingsManager.getSettings(project).getIndentOptionsByFile( - psiFile, null, true, + psiFile, null, false, new Processor() { @Override public boolean process(FileIndentOptionsProvider provider) { From 37f696031169da8ffa782c8b82090f0f3ffb66b2 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 24 Feb 2015 12:26:03 +0300 Subject: [PATCH 182/231] IDEA-136853 readonly locker doesn't work well between splits --- .../status/ToggleReadOnlyAttributePanel.java | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java index b01c167917d9..3b89e81eb1f5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java @@ -20,7 +20,8 @@ import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileEditor.impl.EditorsSplitters; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; @@ -42,13 +43,7 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, @NotNull public Icon getIcon() { - Project project = getProject(); - VirtualFile virtualFile = null; - if (project != null) { - FileEditorManager editorManager = FileEditorManager.getInstance(project); - VirtualFile[] selectedFiles = editorManager.getSelectedFiles(); - virtualFile = selectedFiles.length > 0 ? selectedFiles[0] : null; - } + VirtualFile virtualFile = getCurrentFile(); return virtualFile == null || virtualFile.isWritable() ? AllIcons.Ide.Readwrite : AllIcons.Ide.Readonly; } @@ -82,13 +77,8 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, public Consumer getClickConsumer() { return new Consumer() { public void consume(MouseEvent mouseEvent) { - final Project project = getProject(); - if (project == null) { - return; - } - final FileEditorManager editorManager = FileEditorManager.getInstance(project); - final VirtualFile[] files = editorManager.getSelectedFiles(); - if (!isReadOnlyApplicableForFiles(files)) { + final VirtualFile file = getCurrentFile(); + if (!isReadOnlyApplicableForFile(file)) { return; } FileDocumentManager.getInstance().saveAllDocuments(); @@ -96,11 +86,11 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { try { - ReadOnlyAttributeUtil.setReadOnlyAttribute(files[0], files[0].isWritable()); + ReadOnlyAttributeUtil.setReadOnlyAttribute(file, file.isWritable()); myStatusBar.updateWidget(ID()); } catch (IOException e) { - Messages.showMessageDialog(project, e.getMessage(), UIBundle.message("error.dialog.title"), Messages.getErrorIcon()); + Messages.showMessageDialog(getProject(), e.getMessage(), UIBundle.message("error.dialog.title"), Messages.getErrorIcon()); } } }); @@ -109,20 +99,24 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, } private boolean isReadonlyApplicable() { - final Project project = getProject(); - if (project == null) return false; - final FileEditorManager editorManager = FileEditorManager.getInstance(project); - if (editorManager == null) return false; - VirtualFile[] selectedFiles = editorManager.getSelectedFiles(); - return isReadOnlyApplicableForFiles(selectedFiles); + VirtualFile file = getCurrentFile(); + return isReadOnlyApplicableForFile(file); } - private static boolean isReadOnlyApplicableForFiles(final VirtualFile[] files) { - return files.length > 0 && !files[0].getFileSystem().isReadOnly(); + private static boolean isReadOnlyApplicableForFile(@Nullable VirtualFile file) { + return file != null && !file.getFileSystem().isReadOnly(); } @Nullable private Project getProject() { return CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext((JComponent) myStatusBar)); } + + @Nullable + private VirtualFile getCurrentFile() { + final Project project = getProject(); + if (project == null) return null; + EditorsSplitters splitters = FileEditorManagerEx.getInstanceEx(project).getSplittersFor(myStatusBar.getComponent()); + return splitters.getCurrentFile(); + } } From 596aa7320f9387d80412a15688623ba879a042d3 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 24 Feb 2015 10:26:56 +0100 Subject: [PATCH 183/231] fail-safe isAffected() implementation --- .../src/org/jetbrains/jps/incremental/CompileScopeImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java index 84627a339de8..afb1f271a597 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileScopeImpl.java @@ -84,7 +84,7 @@ public class CompileScopeImpl extends CompileScope { @Override public boolean isAffected(BuildTarget target, @NotNull File file) { if (myFiles.isEmpty()) {//optimization - return true; + return isAffected(target); } final Set files = myFiles.get(target); return files != null && files.contains(file); From 316cd525326506481c1a8d2e5479a035ae293970 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 10:52:53 +0100 Subject: [PATCH 184/231] remove default registry values from user properties --- .../openapi/util/registry/RegistryState.java | 24 ++++----------- .../openapi/util/registry/Registry.java | 29 +++++++++---------- .../openapi/util/registry/RegistryValue.java | 8 +++-- 3 files changed, 25 insertions(+), 36 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java index 73743f86d796..f81c6896b8f6 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java +++ b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,10 +15,12 @@ */ package com.intellij.openapi.util.registry; -import com.intellij.openapi.components.*; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.diagnostic.Logger; import org.jdom.Element; -import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.SortedMap; @@ -28,7 +30,7 @@ import java.util.TreeMap; name = "Registry", storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") ) -public class RegistryState implements BaseComponent, PersistentStateComponent { +public class RegistryState implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance(RegistryState.class); @Override @@ -48,18 +50,4 @@ public class RegistryState implements BaseComponent, PersistentStateComponent myUserProperties = new LinkedHashMap(); - private final Map myLoadedUserProperties = new HashMap(); private final Map myValues = new ConcurrentHashMap(); private static final Registry ourInstance = new Registry(); @@ -119,20 +118,18 @@ public class Registry { } public void loadState(@NotNull Element state) { - final List entries = state.getChildren("entry"); - for (Object each : entries) { - final Element eachEntry = (Element) each; - final String eachKey = eachEntry.getAttributeValue("key"); - final String eachValue = eachEntry.getAttributeValue("value"); - if (eachKey != null && eachValue != null) { - myUserProperties.put(eachKey, eachValue); + myUserProperties.clear(); + for (Element eachEntry : state.getChildren("entry")) { + String key = eachEntry.getAttributeValue("key"); + String value = eachEntry.getAttributeValue("value"); + if (key != null && value != null) { + RegistryValue registryValue = get(key); + if (registryValue.isChangedFromDefault(value)) { + myUserProperties.put(key, value); + registryValue.resetCache(); + } } } - myLoadedUserProperties.putAll(myUserProperties); - - for (RegistryValue each : myValues.values()) { - each.resetCache(); - } } @NotNull @@ -165,11 +162,11 @@ public class Registry { } public boolean isInDefaultState() { - return getUserProperties().isEmpty(); + return myUserProperties.isEmpty(); } public boolean isRestartNeeded() { - return isRestartNeeded(myUserProperties) || isRestartNeeded(myLoadedUserProperties); + return isRestartNeeded(myUserProperties); } private static boolean isRestartNeeded(@NotNull Map map) { diff --git a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java index 22e6214530cf..96ddb5330f1f 100644 --- a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java +++ b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -109,7 +109,11 @@ public class RegistryValue { } public boolean isChangedFromDefault() { - return !asString().equals(getBundleValue(myKey, false)); + return isChangedFromDefault(asString()); + } + + boolean isChangedFromDefault(@NotNull String newValue) { + return !newValue.equals(getBundleValue(myKey, false)); } private String get(@NotNull String key, String defaultValue, boolean isValue) throws MissingResourceException { From 3c92ede90e30789adf4028e3e7ec5ec7934c3ddd Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 24 Feb 2015 11:27:58 +0100 Subject: [PATCH 185/231] Marked as incompatible - scala 1.2.67.3.EAP 1.3.2-14.1 1.3.3-14.1 - ruby 7.0.0.20150216 7.0.0.20150204 - NodeJS 140.2045 - JSTestDriver 140.2109 --- platform/platform-resources/src/brokenPlugins.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index b7f76e554855..f0219611dcb5 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -1,18 +1,18 @@ // This file contains list of broken plugins. // Each line contains plugin ID and list of versions that are broken. // If plugin name or version contains a space you can quote it like in command line. -NodeJS 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 +NodeJS 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141 com.jetbrains.php 139.732 139.659 139.496 139.173 139.105 138.2502 138.2000.2262 138.1751 138.1806 138.1505 138.1161 138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12 com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 -org.jetbrains.plugins.ruby 7.0.0.20141010 7.0.0.20140915 7.0.0.20140901 7.0.0.20140807 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724 +org.jetbrains.plugins.ruby 7.0.0.20150216 7.0.0.20150204 7.0.0.20141010 7.0.0.20140915 7.0.0.20140901 7.0.0.20140807 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724 Pythonid 3.1 4.0.25 4.0.26 Karma 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 -org.intellij.scala 1.0.93.10.EAP 1.0.93.4.EAP 1.0.93.9.EAP 1.0.58 1.0.16 1.0.14 1.0.13 0.42.28 0.42.23 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512 +org.intellij.scala 1.2.67.3.EAP 1.3.2-14.1 1.3.3-14.1 1.0.93.10.EAP 1.0.93.4.EAP 1.0.93.9.EAP 1.0.58 1.0.16 1.0.14 1.0.13 0.42.28 0.42.23 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512 org.jetbrains.kannotator 0.2.420 org.jetbrains.kotlin 0.10.555 0.10.4 0.8.1615 0.7.1360 0.7.1376 0.8.7 SBT 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.5.0 1.5.1 1.6.0 1.6.1 -"JSTestDriver Plugin" 140.1669 140.727 138.317 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 +"JSTestDriver Plugin" 140.2109 140.1669 140.727 138.317 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039 AngularJS 139.1112 139.12 134.1243 134.1341 134.1444 135.1063 135.565 135.831 135.937 138.1242 138.1988 134.1094 0.1.8 0.1.9 com.jetbrains.plugins.ini4idea 0.4 0.5 0.6 0.7 0.8 0.8.1 0.9 0.9.1 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 130.1176 org.jetbrains.plugins.vagrant 0.1 0.2 From af95ee9d298bba78a102f6048c1bddb60754bad4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 11:32:39 +0100 Subject: [PATCH 186/231] store registry state in ide.general.xml --- .../com/intellij/openapi/util/registry/RegistryState.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java index f81c6896b8f6..b988c6251e2e 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java +++ b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java @@ -28,7 +28,10 @@ import java.util.TreeMap; @State( name = "Registry", - storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") + storages = { + @Storage(file = StoragePathMacros.APP_CONFIG + "/ide.general.xml"), + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", deprecated = true) + } ) public class RegistryState implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance(RegistryState.class); From 50bf6337c40ae913e2ef7f4f007fa68accc53218 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 11:43:05 +0100 Subject: [PATCH 187/231] IDEA-133605 set "Access-Control-Request-Headers" to "origin, accept, authorization, content-type" --- platform/platform-impl/src/org/jetbrains/io/NettyUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java index 1415af6cbcd0..0dc92839a0f2 100644 --- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java @@ -225,6 +225,7 @@ public final class NettyUtil { .allowCredentials() .allowNullOrigin() .allowedRequestMethods(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.PATCH) + .allowedRequestHeaders("origin", "accept", "authorization", "content-type") .build())); } From 5108f470b54b9c8fd9e4a41e3845d4274440e38d Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 20 Feb 2015 17:30:40 +0300 Subject: [PATCH 188/231] PY-15136 Sync tree in "Project" toolwindow even if only template directories were changed --- .../configuration/PyContentEntriesModuleConfigurable.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java index a048894adf1a..1e8c8e24a247 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java +++ b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java @@ -104,8 +104,9 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P @Override public void apply() throws ConfigurationException { if (myEditor == null) return; + final boolean editorWasModified = myEditor.isModified(); myEditor.apply(); - if (myModifiableModel.isChanged()) { + if (editorWasModified) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { From 15ddfbf34d17c307301ac00b0d193ba8ed2c632e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 11:50:28 +0100 Subject: [PATCH 189/231] =?UTF-8?q?don't=20set=20ide.firstStartup=20to=20f?= =?UTF-8?q?alse=20in=20tests=20=E2=80=94=20otherwise=20will=20be=20stored?= =?UTF-8?q?=20-=20we=20must=20not=20create=20config=20files=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/intellij/ide/startup/impl/StartupManagerImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java index b1839c87ac10..ad6a9567885c 100644 --- a/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/startup/impl/StartupManagerImpl.java @@ -215,7 +215,10 @@ public class StartupManagerImpl extends StartupManagerEx { } }); - Registry.get("ide.firstStartup").setValue(false); + // otherwise will be stored - we must not create config files in tests + if (!app.isUnitTestMode()) { + Registry.get("ide.firstStartup").setValue(false); + } } public void scheduleInitialVfsRefresh() { From c1b5a46c6dd27327aa8348297f276f84887a4ce5 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Tue, 24 Feb 2015 13:58:44 +0300 Subject: [PATCH 190/231] cosmetics --- .../edu/learning/run/StudySmartChecker.java | 22 ++++++++++--------- .../src/com/jetbrains/edu/EduNames.java | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java index 43928034db0f..bf2b59999b11 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/run/StudySmartChecker.java @@ -27,25 +27,28 @@ public class StudySmartChecker { private StudySmartChecker() { } + private static final Logger LOG = Logger.getInstance(StudySmartChecker.class); public static void smartCheck(@NotNull final AnswerPlaceholder placeholder, - @NotNull final Project project, - @NotNull final VirtualFile answerFile, - @NotNull final TaskFile answerTaskFile, - @NotNull final TaskFile usersTaskFile, - @NotNull final StudyTestRunner testRunner, - @NotNull final VirtualFile virtualFile, - @NotNull final Document usersDocument) { + @NotNull final Project project, + @NotNull final VirtualFile answerFile, + @NotNull final TaskFile answerTaskFile, + @NotNull final TaskFile usersTaskFile, + @NotNull final StudyTestRunner testRunner, + @NotNull final VirtualFile virtualFile, + @NotNull final Document usersDocument) { try { final int index = placeholder.getIndex(); + String windowCopyName = answerFile.getNameWithoutExtension() + index + EduNames.WINDOW_POSTFIX + answerFile.getExtension(); final VirtualFile windowCopy = - answerFile.copy(project, answerFile.getParent(), answerFile.getNameWithoutExtension() + index + EduNames.WINDOW_POSTFIX); + answerFile.copy(project, answerFile.getParent(), windowCopyName); final FileDocumentManager documentManager = FileDocumentManager.getInstance(); final Document windowDocument = documentManager.getDocument(windowCopy); if (windowDocument != null) { - final File resourceFile = StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask()); + final File resourceFile = + StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask()); final TaskFile windowTaskFile = new TaskFile(); TaskFile.copy(answerTaskFile, windowTaskFile); EduDocumentListener listener = new EduDocumentListener(windowTaskFile); @@ -85,5 +88,4 @@ public class StudySmartChecker { LOG.error(e); } } - } diff --git a/python/educational/src/com/jetbrains/edu/EduNames.java b/python/educational/src/com/jetbrains/edu/EduNames.java index 8295735ca9d0..882a2ef9e7ef 100644 --- a/python/educational/src/com/jetbrains/edu/EduNames.java +++ b/python/educational/src/com/jetbrains/edu/EduNames.java @@ -25,7 +25,7 @@ public class EduNames { public static final String TEST_TAB_NAME = "test"; public static final String USER_TEST_INPUT = "input"; public static final String USER_TEST_OUTPUT = "output"; - public static final String WINDOW_POSTFIX = "_window.py"; + public static final String WINDOW_POSTFIX = "_window."; public static final String TASK = "task"; public static final String USER_TESTS = "userTests"; public static final String SANDBOX_DIR = "Sandbox"; From 96a9942f1ae9134748f1ee4074553a6e69b8c261 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Sun, 22 Feb 2015 23:10:43 +0300 Subject: [PATCH 191/231] IDEA-136802 diff: show right help page for dir diff --- .../diff/tools/dir/DifDiffViewer.java | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java index 98786884cb1d..b362604c5f96 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DifDiffViewer.java @@ -23,17 +23,21 @@ import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.contents.FileContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; +import com.intellij.ide.DataManager; import com.intellij.ide.diff.DiffElement; import com.intellij.ide.diff.DirDiffSettings; import com.intellij.ide.diff.JarFileDiffElement; import com.intellij.ide.diff.VirtualFileDiffElement; import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.diff.impl.dir.DirDiffFrame; import com.intellij.openapi.diff.impl.dir.DirDiffPanel; import com.intellij.openapi.diff.impl.dir.DirDiffTableModel; import com.intellij.openapi.diff.impl.dir.DirDiffWindow; import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,7 +50,8 @@ class DifDiffViewer implements FrameDiffTool.DiffViewer { @NotNull private final DiffContext myContext; @NotNull private final ContentDiffRequest myRequest; - @NotNull private final DirDiffPanel myPanel; + @NotNull private final DirDiffPanel myDirDiffPanel; + @NotNull private final JPanel myPanel; public DifDiffViewer(@NotNull DiffContext context, @NotNull ContentDiffRequest request) { myContext = context; @@ -57,7 +62,7 @@ class DifDiffViewer implements FrameDiffTool.DiffViewer { DiffElement element2 = createDiffElement(contents.get(1)); DirDiffTableModel model = new DirDiffTableModel(context.getProject(), element1, element2, new DirDiffSettings()); - myPanel = new DirDiffPanel(model, new DirDiffWindow((DirDiffFrame)null) { + myDirDiffPanel = new DirDiffPanel(model, new DirDiffWindow((DirDiffFrame)null) { @Override public Window getWindow() { return null; @@ -72,31 +77,43 @@ class DifDiffViewer implements FrameDiffTool.DiffViewer { public void setTitle(String title) { } }); + + myPanel = new JPanel(new BorderLayout()); + myPanel.add(myDirDiffPanel.getPanel(), BorderLayout.CENTER); + DataManager.registerDataProvider(myPanel, new DataProvider() { + @Override + public Object getData(@NonNls String dataId) { + if (PlatformDataKeys.HELP_ID.is(dataId)) { + return "reference.dialogs.diff.folder"; + } + return null; + } + }); } @NotNull @Override public FrameDiffTool.ToolbarComponents init() { - myPanel.setupSplitter(); + myDirDiffPanel.setupSplitter(); return new FrameDiffTool.ToolbarComponents(); } @Override public void dispose() { - Disposer.dispose(myPanel); + Disposer.dispose(myDirDiffPanel); } @NotNull @Override public JComponent getComponent() { - return myPanel.getPanel(); + return myPanel; } @Nullable @Override public JComponent getPreferredFocusedComponent() { - return myPanel.getTable(); + return myDirDiffPanel.getTable(); } // From 3753fdd4aa836a3fb3fbf0f70f8fd19a7aea7eb5 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 24 Feb 2015 11:47:50 +0300 Subject: [PATCH 192/231] IDEA-136799 diff: change action title depending on selected file type --- .../diff/actions/CompareFilesAction.java | 41 +++++++++++++++++-- .../src/messages/ActionsBundle.properties | 4 +- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java b/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java index 2e321952643a..4e00df7f1e41 100644 --- a/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java +++ b/platform/diff-impl/src/com/intellij/diff/actions/CompareFilesAction.java @@ -42,8 +42,31 @@ public class CompareFilesAction extends BaseShowDiffAction { VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY); - String text = getTemplatePresentation().getText(); - if (files != null && files.length == 1) text += "..."; + String text = "Compare Files"; + if (files != null && files.length == 1) { + text = "Compare With..."; + } + else if (files != null && files.length == 2) { + Type type1 = getType(files[0]); + Type type2 = getType(files[1]); + + if (type1 != type2) { + text = "Compare"; + } + else { + switch (type1) { + case FILE: + text = "Compare Files"; + break; + case DIRECTORY: + text = "Compare Directories"; + break; + case ARCHIEVE: + text = "Compare Archieves"; + break; + } + } + } e.getPresentation().setText(text); } @@ -93,7 +116,9 @@ public class CompareFilesAction extends BaseShowDiffAction { private static VirtualFile getOtherFile(@Nullable Project project, @NotNull VirtualFile file) { FileChooserDescriptor descriptor; String key; - if (file.isDirectory() || file.getFileType() instanceof ArchiveFileType) { + + Type type = getType(file); + if (type == Type.DIRECTORY || type == Type.ARCHIEVE) { descriptor = new FileChooserDescriptor(false, true, true, false, false, false); key = LAST_USED_FOLDER_KEY; } @@ -121,4 +146,14 @@ public class CompareFilesAction extends BaseShowDiffAction { if (project == null) return; PropertiesComponent.getInstance(project).setValue(key, file.getPath()); } + + @NotNull + private static Type getType(@Nullable VirtualFile file) { + if (file == null) return Type.FILE; + if (file.isDirectory()) return Type.DIRECTORY; + if (file.getFileType() instanceof ArchiveFileType) return Type.ARCHIEVE; + return Type.FILE; + } + + private enum Type {FILE, DIRECTORY, ARCHIEVE} } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 727d96663ff5..89f48f1340cc 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -228,8 +228,8 @@ action.NewClass.text=Java Class action.NewFile.text=File action.NewDir.text=Directory/Package action.NewFromTemplate.text=From Template -action.CompareTwoFiles.text=Compare Two _Files -action.CompareTwoFiles.description=Compare two selected files +action.CompareTwoFiles.text=Compare _Files +action.CompareTwoFiles.description=Compare two selected files or folders action.CompareFileWithEditor.text=Co_mpare File with Editor action.CompareFileWithEditor.description=Compare selected file with editor action.ShowQuickDocAtPinnedWindowFromTooltip.text=Full documentation in a pinned window From 1555db7819bb4e028e9c71fd0650a283b28b5237 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Feb 2015 10:50:01 +0100 Subject: [PATCH 193/231] IDEA-136826 Autocomplete fails for static nested annotations --- .../JavaClassNameCompletionContributor.java | 50 +++++++++++++++---- .../completion/normal/InnerAnnotation.java | 11 ++++ .../normal/InnerAnnotation_after.java | 11 ++++ .../completion/NormalCompletionTest.groovy | 1 + 4 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index d36c35ca6e73..90e550a75b30 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -37,9 +37,11 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Consumer; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Set; import static com.intellij.patterns.PsiJavaPatterns.psiClass; import static com.intellij.patterns.PsiJavaPatterns.psiElement; @@ -117,26 +119,52 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { final boolean pkgContext = JavaCompletionUtil.inSomePackage(insertedElement); AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer() { - @Override - public void consume(PsiClass psiClass) { - if (filter.isAcceptable(psiClass, insertedElement)) { - if (!inJavaContext) { - consumer.consume(AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING)); - } else { - for (JavaPsiClassReferenceElement element : createClassLookupItems(psiClass, afterNew, - JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER, new Condition() { + @Override + public void consume(PsiClass psiClass) { + processClass(psiClass, ContainerUtil.newHashSet(), ""); + } + + private void processClass(PsiClass psiClass, Set visited, String prefix) { + if (!visited.add(psiClass)) return; + + boolean isInnerClass = StringUtil.isNotEmpty(prefix); + if (isInnerClass && isProcessedIndependently(psiClass)) { + return; + } + + if (filter.isAcceptable(psiClass, insertedElement)) { + if (!inJavaContext) { + JavaPsiClassReferenceElement element = AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING); + element.setLookupString(prefix + element.getLookupString()); + consumer.consume(element); + } else { + for (JavaPsiClassReferenceElement element : createClassLookupItems(psiClass, afterNew, + JavaClassNameInsertHandler.JAVA_CLASS_INSERT_HANDLER, new Condition() { @Override public boolean value(PsiClass psiClass) { return filter.isAcceptable(psiClass, insertedElement) && AllClassesGetter.isAcceptableInContext(insertedElement, psiClass, filterByScope, pkgContext); } })) { - consumer.consume(element); - } + element.setLookupString(prefix + element.getLookupString()); + consumer.consume(element); + } + } + } else { + String name = psiClass.getName(); + if (name != null) { + for (PsiClass innerClass : psiClass.getInnerClasses()) { + processClass(innerClass, visited, prefix + name + "."); } } } - }); + } + + private boolean isProcessedIndependently(PsiClass psiClass) { + String innerName = psiClass.getName(); + return innerName != null && matcher.prefixMatches(innerName); + } + }); } static LookupElement highlightIfNeeded(JavaPsiClassReferenceElement element, CompletionParameters parameters) { diff --git a/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java new file mode 100644 index 000000000000..4fd5cc0138d4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation.java @@ -0,0 +1,11 @@ +final class MyModule { + @Target({FIELD,PARAMETER,METHOD}) + @Retention(RUNTIME) + public static @interface Dependency { } +} + +final class SomeService { + + SomeService(@My) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java new file mode 100644 index 000000000000..9ad5271d6b8d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InnerAnnotation_after.java @@ -0,0 +1,11 @@ +final class MyModule { + @Target({FIELD,PARAMETER,METHOD}) + @Retention(RUNTIME) + public static @interface Dependency { } +} + +final class SomeService { + + SomeService(@MyModule.Dependency) { + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index d8abdbd5a9e8..0852028413bf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -932,6 +932,7 @@ public class ListUtils { public void testTabReplacesMethodNameWithLocalVariableName() throws Throwable { doTest('\t'); } public void testMethodParameterAnnotationClass() throws Throwable { doTest(); } + public void testInnerAnnotation() { doTest('\n'); } public void testPrimitiveCastOverwrite() throws Throwable { doTest '\t' } public void testClassReferenceInFor() throws Throwable { doTest ' ' } public void testClassReferenceInFor2() throws Throwable { doTest ' ' } From 1157c15d8e1caf782e3c35efb78137bb6cf72ae9 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Feb 2015 11:24:03 +0100 Subject: [PATCH 194/231] IDEA-136816 Find in Path restricted to module scope does not search non-source paths --- .../com/intellij/find/FindManagerTest.java | 15 +++++++++++++++ .../com/intellij/find/impl/FindInProjectTask.java | 14 ++------------ .../com/intellij/find/impl/FindInProjectUtil.java | 11 ++++------- .../usages/impl/UsageViewManagerTest.java | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java index 8bf2fb1d4284..384fdc3eb339 100644 --- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java +++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java @@ -365,6 +365,19 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { assertSize(1, findUsages(findModel)); } + public void testNonSourceContent() throws Exception { + VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(createTempDirectory()); + PsiTestUtil.addContentRoot(myModule, root); + + createFile(myModule, root, "A.txt", "goo doo"); + + FindModel findModel = FindManagerTestUtils.configureFindModel("goo"); + findModel.setProjectScope(false); + findModel.setModuleName(myModule.getName()); + + assertSize(1, findUsages(findModel)); + } + public void testReplaceRegexp() { FindModel findModel = new FindModel(); findModel.setStringToFind("bug_(?=here)"); @@ -537,6 +550,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { findModel.setFromCursor(false); findModel.setGlobal(true); findModel.setMultipleFiles(true); + findModel.setCustomScope(true); ThrowableRunnable test = new ThrowableRunnable() { @Override @@ -573,6 +587,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase { VirtualFile file = tempDirFixture.createFile("a.txt", "foo bar foo"); FindModel findModel = FindManagerTestUtils.configureFindModel("foo"); findModel.setWholeWordsOnly(true); + findModel.setCustomScope(true); findModel.setCustomScope(new LocalSearchScope(PsiManager.getInstance(myProject).findFile(file))); assertSize(2, findUsages(findModel)); } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index 93e88a25e0fa..973be2bc7416 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -267,7 +267,7 @@ class FindInProjectTask { @NotNull private Collection collectFilesInScope(@NotNull final Set alreadySearched, final boolean skipIndexed) { - SearchScope customScope = myFindModel.getCustomScope(); + SearchScope customScope = myFindModel.isCustomScope() ? myFindModel.getCustomScope() : null; final GlobalSearchScope globalCustomScope = toGlobal(customScope); final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject); @@ -432,17 +432,7 @@ class FindInProjectTask { return Collections.emptySet(); } - SearchScope customScope = myFindModel.getCustomScope(); - GlobalSearchScope scope = myPsiDirectory != null - ? GlobalSearchScopesCore.directoryScope(myPsiDirectory, myFindModel.isWithSubdirectories()) - : myModule != null - ? myModule.getModuleContentScope() - : customScope instanceof GlobalSearchScope - ? (GlobalSearchScope)customScope - : toGlobal(customScope); - if (scope == null) { - scope = ProjectScope.getContentScope(myProject); - } + GlobalSearchScope scope = toGlobal(FindInProjectUtil.getScopeFromModel(myProject, myFindModel)); final Set resultFiles = new LinkedHashSet(); diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 17ca7e4436bf..d22071e66b8e 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -49,10 +49,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.ex.VirtualFileManagerEx; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.GlobalSearchScopesCore; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.SearchScope; +import com.intellij.psi.search.*; import com.intellij.ui.content.Content; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewManager; @@ -443,7 +440,7 @@ public class FindInProjectUtil { } @NotNull - private static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { + static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { SearchScope customScope = findModel.getCustomScope(); PsiDirectory psiDir = getPsiDirectory(findModel, project); VirtualFile directory = psiDir == null ? null : psiDir.getVirtualFile(); @@ -452,8 +449,8 @@ public class FindInProjectUtil { // we don't have to check for myProjectFileIndex.isExcluded(file) here like FindInProjectTask.collectFilesInScope() does // because all found usages are guaranteed to be not in excluded dir directory != null ? GlobalSearchScopesCore.directoryScope(project, directory, findModel.isWithSubdirectories()) : - module != null ? GlobalSearchScope.moduleScope(module) : - findModel.isProjectScope() ? GlobalSearchScope.projectScope(project) : + module != null ? module.getModuleContentScope() : + findModel.isProjectScope() ? ProjectScope.getContentScope(project) : GlobalSearchScope.allScope(project); } } diff --git a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java index 3e38bd2bbb4a..a4fd1b4c881b 100644 --- a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewManagerTest.java @@ -25,6 +25,11 @@ import com.intellij.usages.UsageTarget; import com.intellij.usages.UsageViewManager; public class UsageViewManagerTest extends PlatformTestCase { + + static { + initPlatformLangPrefix(); + } + public void testScopeCreatedForFindInDirectory() { VirtualFile dir = getProject().getBaseDir(); FindModel findModel = new FindModel(); @@ -36,4 +41,14 @@ public class UsageViewManagerTest extends PlatformTestCase { SearchScope scope = manager.getMaxSearchScopeToWarnOfFallingOutOf(new UsageTarget[]{target}); assertEquals(scope, GlobalSearchScopesCore.directoryScope(getProject(), dir, true)); } + + public void testScopeCreatedForFindInModuleContent() { + FindModel findModel = new FindModel(); + findModel.setModuleName(getModule().getName()); + findModel.setProjectScope(false); + UsageTarget target = new FindInProjectUtil.StringUsageTarget(getProject(), findModel); + UsageViewManagerImpl manager = (UsageViewManagerImpl)UsageViewManager.getInstance(getProject()); + SearchScope scope = manager.getMaxSearchScopeToWarnOfFallingOutOf(new UsageTarget[]{target}); + assertEquals(scope, getModule().getModuleContentScope()); + } } From 9e7d6766dafb4095dcf95e5950af88e831da2337 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 24 Feb 2015 12:14:03 +0100 Subject: [PATCH 195/231] cleanup --- .../daemon/DaemonCodeAnalyzerSettings.java | 20 +++++++++---------- .../DaemonCodeAnalyzerSettingsImpl.java | 10 +++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java index 00fa3f0f4cff..9fc611d6dbbc 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.codeInsight.daemon; import com.intellij.openapi.components.ServiceManager; +import com.intellij.util.xmlb.annotations.OptionTag; import com.intellij.util.xmlb.annotations.Transient; public class DaemonCodeAnalyzerSettings { @@ -26,9 +26,9 @@ public class DaemonCodeAnalyzerSettings { public boolean NEXT_ERROR_ACTION_GOES_TO_ERRORS_FIRST = true; public int AUTOREPARSE_DELAY = 300; - public boolean SHOW_ADD_IMPORT_HINTS = true; + protected boolean myShowAddImportHints = true; public String NO_AUTO_IMPORT_PATTERN = "[a-z].?"; - public boolean SUPPRESS_WARNINGS = true; + protected boolean mySuppressWarnings = true; public boolean SHOW_METHOD_SEPARATORS = false; public int ERROR_STRIPE_MARK_MIN_HEIGHT = 2; public boolean SHOW_SMALL_ICONS_IN_GUTTER = true; @@ -38,21 +38,21 @@ public class DaemonCodeAnalyzerSettings { return false; } - @Transient + @OptionTag(value = "SHOW_ADD_IMPORT_HINTS") public boolean isImportHintEnabled() { - return SHOW_ADD_IMPORT_HINTS; + return myShowAddImportHints; } public void setImportHintEnabled(boolean isImportHintEnabled) { - SHOW_ADD_IMPORT_HINTS = isImportHintEnabled; + myShowAddImportHints = isImportHintEnabled; } - @Transient + @OptionTag(value = "SUPPRESS_WARNINGS") public boolean isSuppressWarnings() { - return SUPPRESS_WARNINGS; + return mySuppressWarnings; } public void setSuppressWarnings(boolean suppressWarnings) { - SUPPRESS_WARNINGS = suppressWarnings; + mySuppressWarnings = suppressWarnings; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java index d4889a97f802..0334f18b0931 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/DaemonCodeAnalyzerSettingsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,13 +24,13 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProfileManagerImpl; -import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; +import com.intellij.util.xmlb.SkipDefaultsSerializationFilter; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; @State( name = "DaemonCodeAnalyzerSettings", - storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml")} + storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml") ) public class DaemonCodeAnalyzerSettingsImpl extends DaemonCodeAnalyzerSettings implements PersistentStateComponent, Cloneable { @Override @@ -42,7 +42,7 @@ public class DaemonCodeAnalyzerSettingsImpl extends DaemonCodeAnalyzerSettings i public DaemonCodeAnalyzerSettingsImpl clone() { DaemonCodeAnalyzerSettingsImpl settings = new DaemonCodeAnalyzerSettingsImpl(); settings.AUTOREPARSE_DELAY = AUTOREPARSE_DELAY; - settings.SHOW_ADD_IMPORT_HINTS = SHOW_ADD_IMPORT_HINTS; + settings.myShowAddImportHints = myShowAddImportHints; settings.SHOW_METHOD_SEPARATORS = SHOW_METHOD_SEPARATORS; settings.NO_AUTO_IMPORT_PATTERN = NO_AUTO_IMPORT_PATTERN; settings.SHOW_SMALL_ICONS_IN_GUTTER = SHOW_SMALL_ICONS_IN_GUTTER; @@ -51,7 +51,7 @@ public class DaemonCodeAnalyzerSettingsImpl extends DaemonCodeAnalyzerSettings i @Override public Element getState() { - Element element = XmlSerializer.serialize(this, new SkipDefaultValuesSerializationFilters()); + Element element = XmlSerializer.serialize(this, new SkipDefaultsSerializationFilter()); String profile = InspectionProfileManager.getInstance().getRootProfile().getName(); if (!"Default".equals(profile)) { element.setAttribute("profile", profile); From 0b7cece21554d69a7a087d3e26eaf8cb572e197b Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 24 Feb 2015 14:47:10 +0300 Subject: [PATCH 196/231] IDEA-136848 Error splitting a comment by pressing Enter --- .../com/intellij/codeInsight/editorActions/EnterHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java index b6f951efb865..449f0865f793 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java @@ -356,7 +356,7 @@ public class EnterHandler extends BaseEnterHandler { commentContext.docStart = false; } else { - commentContext.docAsterisk = true; + commentContext.docAsterisk = CodeStyleSettingsManager.getSettings(getProject()).JD_LEADING_ASTERISKS_ARE_ENABLED; commentContext.docStart = false; } } From 761971622024603d948ef1ceac0ad827a22380c8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Feb 2015 12:26:56 +0100 Subject: [PATCH 197/231] advance MultipleModuleHighlightingTest bombs --- .../codeInsight/MultipleModuleHighlightingTest.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy index 05a14ef267f0..b02d90b6d596 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleModuleHighlightingTest.groovy @@ -25,7 +25,7 @@ import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase */ class MultipleModuleHighlightingTest extends JavaCodeInsightFixtureTestCase { - @Bombed(day = 1, month = Calendar.MARCH) + @Bombed(day = 1, month = Calendar.APRIL) public void "test use original place classpath for reference type resolving"() { addTwoModules() @@ -60,7 +60,7 @@ class Class3 { myFixture.checkHighlighting() } - @Bombed(day = 1, month = Calendar.MARCH) + @Bombed(day = 1, month = Calendar.APRIL) public void "test use original place classpath for new expression type resolving"() { addTwoModules() From 81f5cc5e4c02882876bea8312f7e2c72f1fdf34b Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 24 Feb 2015 12:49:50 +0100 Subject: [PATCH 198/231] a registry key to turn off PsiClassImplUtil.correctType --- .../src/com/intellij/psi/impl/PsiClassImplUtil.java | 7 ++++++- platform/util/resources/misc/registry.properties | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 67143a7b73a5..2a03a31bb3ea 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.*; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -711,6 +712,10 @@ public class PsiClassImplUtil { @Nullable public static PsiClassType correctType(PsiClassType originalType, final GlobalSearchScope resolveScope) { + if (!Registry.is("java.correct.class.type.by.place.resolve.scope")) { + return originalType; + } + final PsiClassType.ClassResolveResult originalResolveResult = originalType.resolveGenerics(); PsiClass superClass = originalResolveResult.getElement(); if (superClass == null) { @@ -746,7 +751,7 @@ public class PsiClassImplUtil { } }); if (substitute == null) return null; - + substitutor = substitutor.put(typeParameters[i], substitute); } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index c324e0870738..1613d3e292e3 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -257,6 +257,9 @@ java.annotations.inference.nullable.method.description=Restart is required; infe java.annotations.inference.nullable.method.transitivity=true java.annotations.inference.nullable.method.transitivity.description=Restart is required; if a method result is a call to a @Nullable method, reports the caller as @Nullable as well +java.correct.class.type.by.place.resolve.scope=true +java.correct.class.type.by.place.resolve.scope.description=When resolving Java references, use the resolve scope of the currently processed source file + documentation.component.editor.font=false ide.completion.show.better.matching.classes=true From 5f93bf78bd8c63f499e84a3a9e3bc7519535ed68 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 13:29:26 +0300 Subject: [PATCH 199/231] any attributes cache should be dropped on exit from dumb mode --- .../daemon/XmlHighlightingTest.java | 24 ++++++++++++++++++- .../impl/schema/ComplexTypeDescriptor.java | 16 ++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java index d88422df2127..3d0ade45ff0a 100644 --- a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java +++ b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java @@ -49,6 +49,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.project.DumbServiceImpl; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; @@ -64,6 +65,7 @@ import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.XmlAttributeDescriptor; import com.intellij.xml.XmlBundle; +import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.impl.schema.XmlElementDescriptorImpl; import com.intellij.xml.util.*; import gnu.trove.THashSet; @@ -1422,7 +1424,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase { Editor[] allEditors = EditorFactory.getInstance().getAllEditors(); final Editor schemaEditor = allEditors[0] == myEditor ? allEditors[1]:allEditors[0]; final String text = schemaEditor.getDocument().getText(); - final String newText = text.replaceAll("xsd","xs"); + final String newText = text.replaceAll("xsd", "xs"); WriteCommandAction.runWriteCommandAction(null, new Runnable(){ @Override public void run() { @@ -2082,6 +2084,26 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase { assertTrue(resolve instanceof XmlTag); } + public void testDropAnyAttributeCacheOnExitFromDumbMode() throws Exception { + try { + DumbServiceImpl.getInstance(myProject).setDumb(true); + configureByFiles(null, getVirtualFile(BASE_PATH + "AnyAttributeNavigation/test.xml"), + getVirtualFile(BASE_PATH + "AnyAttributeNavigation/test.xsd"), + getVirtualFile(BASE_PATH + "AnyAttributeNavigation/library.xsd")); + PsiReference at = getFile().findReferenceAt(getEditor().getCaretModel().getOffset()); + + XmlTag tag = PsiTreeUtil.getParentOfType(at.getElement(), XmlTag.class); + XmlElementDescriptor descriptor = tag.getDescriptor(); + XmlAttributeDescriptor[] descriptors = descriptor.getAttributesDescriptors(tag); + System.out.println(Arrays.asList(descriptors)); + } + finally { + DumbServiceImpl.getInstance(myProject).setDumb(false); + } + + doDoTest(true, false); + } + public void testQualifiedAttributeReference() throws Exception { configureByFiles(null, BASE_PATH + "qualified.xml", BASE_PATH + "qualified.xsd"); doDoTest(true, false); diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java index e86f655bc6d1..d246a0e8616f 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java @@ -15,10 +15,11 @@ */ package com.intellij.xml.impl.schema; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.FieldCache; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.util.CachedValue; @@ -85,17 +86,26 @@ public class ComplexTypeDescriptor extends TypeDescriptor { } }; + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private final FactoryMap> myAnyAttributeCache = new ConcurrentFactoryMap>() { @Override protected CachedValue create(final String key) { return CachedValuesManager.getManager(myTag.getProject()).createCachedValue(new CachedValueProvider() { @Override public Result compute() { - THashSet dependencies = new THashSet(); + THashSet dependencies = new THashSet(); CanContainAttributeType type = _canContainAttribute(key, myTag, null, new THashSet(), dependencies); if (dependencies.isEmpty()) { dependencies.add(myTag.getContainingFile()); } + if (DumbService.isDumb(myTag.getProject())) { + dependencies.add(new ModificationTracker() { + @Override + public long getModificationCount() { + return DumbService.isDumb(myTag.getProject()) ? 0 : 1; + } + }); + } return Result.create(type, ArrayUtil.toObjectArray(dependencies)); } }, false); @@ -398,7 +408,7 @@ public class ComplexTypeDescriptor extends TypeDescriptor { XmlTag tag, @Nullable String qName, Set visited, - @Nullable Set dependencies) { + @Nullable Set dependencies) { if (XmlNSDescriptorImpl.equalsToSchemaName(tag, "anyAttribute")) { if (dependencies != null) { dependencies.add(tag.getContainingFile()); From df0b269304a0c5a327946176349109500ed2ddc0 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 14:54:46 +0300 Subject: [PATCH 200/231] cleanup --- .../src/com/intellij/javaee/ExternalResourceManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java b/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java index 05f7d7c037ca..0c5a63e57b5a 100644 --- a/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java +++ b/xml/xml-psi-api/src/com/intellij/javaee/ExternalResourceManager.java @@ -38,7 +38,7 @@ public abstract class ExternalResourceManager extends SimpleModificationTracker public abstract void removeResource(@NotNull String url, @Nullable String version); /** - * @see #getResourceLocation(String, com.intellij.openapi.project.Project) + * @see #getResourceLocation(String, Project) */ @Deprecated public abstract String getResourceLocation(@NotNull @NonNls String url); From 6b402e0f9726017fbc77a054bacdbae9d1ef9d36 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 14:56:04 +0300 Subject: [PATCH 201/231] test fixed --- .../com/intellij/codeInsight/daemon/XmlHighlightingTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java index 3d0ade45ff0a..d30c87b7bfd3 100644 --- a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java +++ b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java @@ -1769,7 +1769,7 @@ public class XmlHighlightingTest extends DaemonAnalyzerTestCase { final String testName = getTestName(false); String[][] urls = { {"urn:jboss:bean-deployer:2.0", testName + ".xsd"}, - {null, testName + "_2.xsd"} + {"", testName + "_2.xsd"} }; doTestWithLocations(urls,"xml"); } From 04b7ec03f1825b9df9d6a3810de3a856b55d5013 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Tue, 24 Feb 2015 15:07:52 +0300 Subject: [PATCH 202/231] get course language from stepic --- .../src/com/jetbrains/edu/stepic/CourseInfo.java | 12 ++++++++++-- .../com/jetbrains/edu/stepic/EduStepicConnector.java | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java b/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java index 161dc10b059b..38815badc45b 100644 --- a/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java +++ b/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java @@ -15,14 +15,18 @@ public class CourseInfo { private String myName; @SerializedName("summary") private String myDescription; + @SerializedName("course_format") + //course type in format "pycharm " + private String myType; private String myAuthor; - public static CourseInfo INVALID_COURSE = new CourseInfo("", "", ""); + public static CourseInfo INVALID_COURSE = new CourseInfo("", "", "", ""); - public CourseInfo(String name, String author, String description) { + public CourseInfo(String name, String author, String description, String type) { myName = name; myAuthor = author; myDescription = description; + myType = type; } public String getName() { @@ -37,6 +41,10 @@ public class CourseInfo { return myDescription; } + public String getType() { + return myType; + } + @Override public String toString() { return myName; diff --git a/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java b/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java index a6e45bbd7c03..56bd969aa9f8 100644 --- a/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java +++ b/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java @@ -41,6 +41,8 @@ public class EduStepicConnector { private static final String ourDomain = "stepic.org"; private static String ourSessionId = "524iethiwju2tjywaqmf7tbwx0p0jk1b"; private static String ourCSRFToken = "LJ9n6OyLVA7hxU94dlYWUu65MF51Nx37"; + //this prefix indicates that course can be opened by educational plugin + public static final String PYCHARM_PREFIX = "pycharm "; private EduStepicConnector() { } @@ -84,7 +86,8 @@ public class EduStepicConnector { course.setAuthor(info.getAuthor()); course.setDescription(info.getDescription()); course.setName(info.getName()); - course.setLanguage("Python"); // TODO: get from stepic + String courseType = info.getType(); + course.setLanguage(courseType.substring(PYCHARM_PREFIX.length())); course.setUpToDate(true); // TODO: get from stepic try { for (Integer section : info.sections) { From baad9149e1d609e7f035f69e7787132dde38756c Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 24 Feb 2015 13:10:54 +0100 Subject: [PATCH 203/231] Karma:140.2109 was marked as incompatible --- platform/platform-resources/src/brokenPlugins.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index f0219611dcb5..d9fe7ef3fa2b 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -7,7 +7,7 @@ com.jetbrains.lang.ejs 131.17 131.12 com.jetbrains.twig 133.51 130.1639 org.jetbrains.plugins.ruby 7.0.0.20150216 7.0.0.20150204 7.0.0.20141010 7.0.0.20140915 7.0.0.20140901 7.0.0.20140807 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724 Pythonid 3.1 4.0.25 4.0.26 -Karma 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 +Karma 140.2109 138.1684 138.1879 138.317 138.21 134.1163 134.1039 134.686 134.31 org.intellij.scala 1.2.67.3.EAP 1.3.2-14.1 1.3.3-14.1 1.0.93.10.EAP 1.0.93.4.EAP 1.0.93.9.EAP 1.0.58 1.0.16 1.0.14 1.0.13 0.42.28 0.42.23 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512 org.jetbrains.kannotator 0.2.420 org.jetbrains.kotlin 0.10.555 0.10.4 0.8.1615 0.7.1360 0.7.1376 0.8.7 From 4fa0df5db3a5ae02a516b1e6e7ac79752d35534c Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 23 Feb 2015 15:49:41 +0300 Subject: [PATCH 204/231] IDEA-135623 fix change type detection Create a fake EmptyTextFilePatch which doesn't hold any patch texts, but only detects the file type. A better fix would be to return different kinds of FilePatches in different situations, but since everything resides in vcs-api, it's better not to break compatibility until really necessary. --- .../openapi/diff/impl/patch/PatchReader.java | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java index 0e51740f4c48..f17109fe4353 100644 --- a/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java +++ b/platform/vcs-api/src/com/intellij/openapi/diff/impl/patch/PatchReader.java @@ -55,10 +55,10 @@ public class PatchReader { this(patchContent, true); } - public PatchReader(CharSequence patchContent, boolean parseHunks) { + public PatchReader(CharSequence patchContent, boolean saveHunks) { myLines = LineTokenizer.tokenizeIntoList(patchContent, false); - myAdditionalInfoParser = new AdditionalInfoParser(!parseHunks); - myPatchContentParser = new PatchContentParser(parseHunks); + myAdditionalInfoParser = new AdditionalInfoParser(!saveHunks); + myPatchContentParser = new PatchContentParser(saveHunks); } public List readAllPatches() throws PatchSyntaxException { @@ -254,15 +254,15 @@ public class PatchReader { private static class PatchContentParser implements Parser { - private final boolean myParseHunks; + private final boolean mySaveHunks; private DiffFormat myDiffFormat = null; private final List myPatches; private boolean myDiffCommandLike; private boolean myIndexLike; - private PatchContentParser(boolean parseHunks) { - myParseHunks = parseHunks; + private PatchContentParser(boolean saveHunks) { + mySaveHunks = saveHunks; myPatches = new SmartList(); } @@ -303,7 +303,7 @@ public class PatchReader { } private TextFilePatch readPatch(String curLine, ListIterator iterator) throws PatchSyntaxException { - final TextFilePatch curPatch = new TextFilePatch(null); + final TextFilePatch curPatch = mySaveHunks ? new TextFilePatch(null) : new EmptyTextFilePatch(); extractFileName(curLine, curPatch, true, myDiffCommandLike && myIndexLike); if (! iterator.hasNext()) throw new PatchSyntaxException(iterator.previousIndex(), "Second file name expected"); @@ -314,7 +314,7 @@ public class PatchReader { } extractFileName(curLine, curPatch, false, myDiffCommandLike && myIndexLike); - while (myParseHunks && iterator.hasNext()) { + while (iterator.hasNext()) { PatchHunk hunk; if (myDiffFormat == DiffFormat.UNIFIED) { hunk = readNextHunkUnified(iterator); @@ -595,4 +595,37 @@ public class PatchReader { boolean testIsStart(final String start); void parse(final String start, final ListIterator iterator) throws PatchSyntaxException; } + + private static class EmptyTextFilePatch extends TextFilePatch { + private int myHunkCount = 0; + private boolean myNew; + private boolean myDeleted; + + EmptyTextFilePatch() { + super(null); + } + + @Override + public void addHunk(PatchHunk hunk) { + if (myHunkCount == 0) { + if (hunk.isNewContent()) { + myNew = true; + } + else if (hunk.isDeletedContent()) { + myDeleted = true; + } + } + myHunkCount++; + } + + @Override + public boolean isNewFile() { + return myHunkCount == 1 && myNew; + } + + @Override + public boolean isDeletedFile() { + return myHunkCount == 1 && myDeleted; + } + } } From 259930857a2fef1f6304e552bd37c8caffc2b3b0 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 24 Feb 2015 15:22:46 +0300 Subject: [PATCH 205/231] [vcs-log] minor: Selection explicitly depends on VcsLogGraphTable and therefore can be static --- .../vcs/log/ui/frame/VcsLogGraphTable.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index ab79d9af9be1..5f5aa460d640 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -399,23 +399,25 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C @NotNull public Selection getSelection() { - return new Selection(); + return new Selection(this); } - public class Selection { + public static class Selection { private final TIntHashSet myCommits; + private final VcsLogGraphTable myTable; - public Selection() { - myCommits = getCommitsAtRows(myDataPack.getVisibleGraph(), getSelectedRows()); + public Selection(@NotNull VcsLogGraphTable table) { + myTable = table; + myCommits = getCommitsAtRows(myTable.myDataPack.getVisibleGraph(), myTable.getSelectedRows()); } public void restore(@NotNull VisibleGraph newVisibleGraph) { - TIntHashSet rowsToSelect = findNewRowsToSelect(getGraphTableModel(), newVisibleGraph, myCommits); + TIntHashSet rowsToSelect = findNewRowsToSelect(myTable.getGraphTableModel(), newVisibleGraph, myCommits); if (!rowsToSelect.isEmpty()) { rowsToSelect.forEach(new TIntProcedure() { @Override public boolean execute(int row) { - addRowSelectionInterval(row, row); + myTable.addRowSelectionInterval(row, row); return true; } }); From fcc7bb1bc6cd903296e1f408652c9cf9e3684182 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 15:43:33 +0300 Subject: [PATCH 206/231] ModificationTracker fro dumb mode --- .../com/intellij/openapi/project/DumbService.java | 6 ++++++ .../intellij/openapi/project/DumbServiceImpl.java | 15 ++++++++++++++- .../xml/impl/schema/ComplexTypeDescriptor.java | 8 +------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index 68ca99133e46..0bd0ab7176f4 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.openapi.util.Ref; import com.intellij.util.messages.Topic; @@ -50,6 +51,11 @@ public abstract class DumbService { */ public static final Topic DUMB_MODE = new Topic("dumb mode", DumbModeListener.class); + /** + * The tracker is advanced each time we enter/exit from dumb mode. + */ + public abstract ModificationTracker getModificationTracker(); + /** * @return whether IntelliJ IDEA is in dumb mode, which means that right now indices are updated in background. * IDEA offers only limited functionality at such times, e.g. plain text file editing and version control operations. diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 4932c584a1e5..6b9b702ad443 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -49,10 +49,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Map; -public class DumbServiceImpl extends DumbService implements Disposable { +public class DumbServiceImpl extends DumbService implements Disposable, ModificationTracker { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.project.DumbServiceImpl"); private volatile boolean myDumb = false; private final DumbModeListener myPublisher; + private long myModificationCount; private final Queue myUpdatesQueue = new Queue(5); /** @@ -116,6 +117,11 @@ public class DumbServiceImpl extends DumbService implements Disposable { myAlternativeResolution.set(enabled); } + @Override + public ModificationTracker getModificationTracker() { + return null; + } + @Override public boolean isDumb() { return myDumb; @@ -209,6 +215,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { @Override public Boolean compute() { myDumb = true; + myModificationCount++; try { myPublisher.enteredDumbMode(); } @@ -236,6 +243,7 @@ public class DumbServiceImpl extends DumbService implements Disposable { private void updateFinished() { myDumb = false; + myModificationCount++; if (myProject.isDisposed()) return; if (ApplicationManager.getApplication().isInternal()) LOG.info("updateFinished"); @@ -440,6 +448,11 @@ public class DumbServiceImpl extends DumbService implements Disposable { return result.get(); } + @Override + public long getModificationCount() { + return myModificationCount; + } + private class AppIconProgress extends ProgressIndicatorBase { private double lastFraction; diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java index d246a0e8616f..c18db0fec59d 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/ComplexTypeDescriptor.java @@ -18,7 +18,6 @@ package com.intellij.xml.impl.schema; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.FieldCache; -import com.intellij.openapi.util.ModificationTracker; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider; import com.intellij.psi.meta.PsiMetaData; @@ -99,12 +98,7 @@ public class ComplexTypeDescriptor extends TypeDescriptor { dependencies.add(myTag.getContainingFile()); } if (DumbService.isDumb(myTag.getProject())) { - dependencies.add(new ModificationTracker() { - @Override - public long getModificationCount() { - return DumbService.isDumb(myTag.getProject()) ? 0 : 1; - } - }); + dependencies.add(DumbService.getInstance(myTag.getProject()).getModificationTracker()); } return Result.create(type, ArrayUtil.toObjectArray(dependencies)); } From c6d1c6dd537509335406e32de72230165b813cc7 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 15:44:58 +0300 Subject: [PATCH 207/231] javadoc moved --- .../intellij/openapi/project/DumbService.java | 3 --- .../intellij/openapi/wm/ToolWindowManager.java | 16 ++++++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index 0bd0ab7176f4..efd18fbf8805 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -38,9 +38,6 @@ import java.util.List; * A service managing IDEA's 'dumb' mode: when indices are updated in background and the functionality is very much limited. * Only the explicitly allowed functionality is available. Usually it's allowed by implementing {@link DumbAware} interface. * - * If you want to register a toolwindow, which will be enabled during the dumb mode, please use {@link com.intellij.openapi.wm.ToolWindowManager}'s - * registration methods which have 'canWorkInDumMode' parameter. - * * @author peter */ public abstract class DumbService { diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java index 654f43e0c2ec..d0a875598203 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java @@ -25,6 +25,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.HyperlinkListener; +/** + * If you want to register a toolwindow, which will be enabled during the dumb mode, please use {@link ToolWindowManager}'s + * registration methods which have 'canWorkInDumMode' parameter. + */ public abstract class ToolWindowManager { public abstract boolean canShowNotification(@NotNull String toolWindowId); @@ -37,22 +41,22 @@ public abstract class ToolWindowManager { * Register specified tool window into IDE window system. * @param id id of tool window to be registered. * @param component component which represents tool window content. - * May be null. Content can be further added via content manager for this tool window (See {@link com.intellij.openapi.wm.ToolWindow#getContentManager()}) + * May be null. Content can be further added via content manager for this tool window (See {@link ToolWindow#getContentManager()}) * @param anchor the default anchor for first registration. It uses only first time the * tool window with the specified id is being registered into the window system. * After the first registration window's anchor is stored in project file * and anchor is ignored. - * @exception java.lang.IllegalArgumentException if the same window is already installed or one + * @exception IllegalArgumentException if the same window is already installed or one * of the parameters is null. * @return tool window - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor); /** - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull @@ -62,7 +66,7 @@ public abstract class ToolWindowManager { @NotNull Disposable parentDisposable); /** - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull @@ -72,7 +76,7 @@ public abstract class ToolWindowManager { Disposable parentDisposable, boolean canWorkInDumbMode); /** - * @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} + * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} */ @Deprecated @NotNull From 936dc830f8210ed1cf4d95ba8e149520f870b0fb Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 24 Feb 2015 16:29:19 +0300 Subject: [PATCH 208/231] Update javadoc and toString for CustomTaskState --- .../com/intellij/tasks/CustomTaskState.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java index 0fced6c7af52..d875b3049281 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java @@ -22,6 +22,12 @@ public class CustomTaskState { myPresentableName = name; } + /** + * Unique ID (e.g. number or unique name) of this state that can be used later to update state of an issue + * in {@link TaskRepository#setTaskState(Task, CustomTaskState)}. + * + * @see TaskRepository#setTaskState(Task, CustomTaskState) + */ @NotNull public String getId() { return myId; @@ -34,6 +40,9 @@ public class CustomTaskState { myId = id; } + /** + * Text that describes this state and will be shown to user in UI (unlike ID it's not necessarily unique). + */ @NotNull public String getPresentableName() { return myPresentableName; @@ -61,6 +70,16 @@ public class CustomTaskState { return myId.hashCode(); } + /** + * Creates custom state for which ID is identical to {@link TaskState#name} of the given predefined state and {@link #isPredefined()} + * returns true. If your repository provides only fixed set of available states, that are one of those described in {@link TaskState}, + * you may find this methods useful to implement {@link TaskRepository#getAvailableTaskStates(Task)}. + * + * @return custom task state that represents given predefined state + * @see #asPredefined() + * @see #isPredefined() + * @see TaskRepository#getAvailableTaskStates(Task) + */ @NotNull public static CustomTaskState fromPredefined(@NotNull TaskState state) { final CustomTaskState result = new CustomTaskState(state.name(), state.getPresentableName()); @@ -68,6 +87,13 @@ public class CustomTaskState { return result; } + /** + * Returns corresponding value of {@link TaskState} that has the same name as ID of this state. + * It's intended to be used for custom states created using {@link #fromPredefined}. + * + * @return predefined task state as described or {@code null} if such state doesn't exists or {@link #isPredefined()} returns false + * @see #isPredefined() + */ @Nullable public TaskState asPredefined() { if (isPredefined()) { @@ -80,6 +106,12 @@ public class CustomTaskState { return null; } + /** + * Means that this custom state can be directly mapped to legacy {@link TaskState}. If it's false, {@link #asPredefined()} returns {@code null}. + * It's intended to be used mainly for compatibility with existing repositories. + * + * @see #asPredefined() + */ private boolean isPredefined() { return myPredefined; } @@ -93,6 +125,6 @@ public class CustomTaskState { @Override public String toString() { - return "CustomTaskState(id='" + myId + '\'' + ", name='" + myPresentableName + '\'' + ", myPredefined=" + myPredefined + ')'; + return "CustomTaskState(id='" + myId + '\'' + ", name='" + myPresentableName + '\'' + ", predefined=" + myPredefined + ')'; } } From baa452a7a5f97815f0451c9dd2d17869778b9a1c Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Feb 2015 16:44:47 +0300 Subject: [PATCH 209/231] ModificationTracker fro dumb mode --- .../core-impl/src/com/intellij/mock/MockDumbService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/core-impl/src/com/intellij/mock/MockDumbService.java b/platform/core-impl/src/com/intellij/mock/MockDumbService.java index b1fe7ae2a727..e97a9f64c7f3 100644 --- a/platform/core-impl/src/com/intellij/mock/MockDumbService.java +++ b/platform/core-impl/src/com/intellij/mock/MockDumbService.java @@ -22,6 +22,8 @@ import com.intellij.openapi.project.DumbModeTask; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.ModificationTracker; +import com.intellij.openapi.util.SimpleModificationTracker; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -36,6 +38,11 @@ public class MockDumbService extends DumbService { myProject = project; } + @Override + public ModificationTracker getModificationTracker() { + return new SimpleModificationTracker(); + } + @Override public boolean isDumb() { return false; From a82affb64953489fe47a707cfb48e2103650c43b Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Tue, 24 Feb 2015 16:29:57 +0300 Subject: [PATCH 210/231] New lcd contrast values --- platform/util/src/com/intellij/util/ui/UIUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 3a8b93a92b11..566625c7378b 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1773,8 +1773,8 @@ public class UIUtil { } private static int THEME_BASED_TEXT_LCD_CONTRAST = 0; - private static int BEST_DARK_LCD_CONTRAST = 100; - private static int BEST_LIGHT_LCD_CONTRAST = 200; + private static int BEST_DARK_LCD_CONTRAST = 250; + private static int BEST_LIGHT_LCD_CONTRAST = 100; public static void setHintingForLCDText(Graphics2D g2d) { From 0360aeded1a1a3fd3c8c2715b09a63a8d70c060c Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 24 Feb 2015 16:45:00 +0300 Subject: [PATCH 211/231] EA-63794 - PIEAE: LeafPsiElement.invalid --- .../com/intellij/debugger/SourcePosition.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index fc13858daac9..d10b656ad6a8 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -307,7 +307,10 @@ public abstract class SourcePosition implements Navigatable{ } public static SourcePosition createFromElement(PsiElement element) { - final PsiElement navigationElement = element.getNavigationElement(); + ApplicationManager.getApplication().assertReadAccessAllowed(); + PsiElement navigationElement = element.getNavigationElement(); + final SmartPsiElementPointer pointer = + SmartPointerManager.getInstance(navigationElement.getProject()).createSmartPsiElementPointer(navigationElement); final PsiFile psiFile; if (JspPsiUtil.isInJspFile(navigationElement)) { psiFile = JspPsiUtil.getJspFile(navigationElement); @@ -318,12 +321,19 @@ public abstract class SourcePosition implements Navigatable{ return new SourcePositionCache(psiFile) { @Override protected PsiElement calcPsiElement() { - return navigationElement; + ApplicationManager.getApplication().assertReadAccessAllowed(); + return pointer.getElement(); } @Override protected int calcOffset() { - return navigationElement.getTextOffset(); + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Integer compute() { + PsiElement elem = pointer.getElement(); + return elem != null ? elem.getTextOffset() : -1; + } + }); } }; } From aa1b472dff1e1835a18f5b768578d9f03004fe79 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 24 Feb 2015 12:06:33 +0100 Subject: [PATCH 212/231] mew inference: checked exceptions with incompatible bounds --- ...eckedExceptionCompatibilityConstraint.java | 2 +- ...edExceptionsConstraintsSubstitutions1.java | 38 +++++++++++++++++++ .../lambda/NewLambdaHighlightingTest.java | 4 ++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java index 87eb8b804b08..cf974c91f980 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -176,7 +176,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai private static boolean isAddressed(List expectedThrownTypes, PsiType thrownType) { for (PsiType expectedThrownType : expectedThrownTypes) { - if (TypeConversionUtil.isAssignable(expectedThrownType, thrownType)) { + if (TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(thrownType), expectedThrownType)) { return true; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java new file mode 100644 index 000000000000..476d30ab3cf2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CheckedExceptionsConstraintsSubstitutions1.java @@ -0,0 +1,38 @@ +import java.io.IOException; + +class Test { + + interface B { + K l(K k) throws E; + } + + void bar(B b) {} + + T baz(T l) throws E { + return null; + } + + { + bar(l -> baz(l)); + bar(this::baz); + } +} +class Test1 { + + interface B { + K l(K k) throws E; + } + + void bar(B b) {} + + class MyEx extends Exception{} + + T baz(T l) throws E { + return null; + } + + { + bar(l -> baz(l)); + bar(this::baz); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index ca5ce7e44e96..f0636eb92e57 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -142,6 +142,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testCheckedExceptionsConstraintsSubstitutions1() throws Exception { + doTest(); + } + public void testCheckedExceptionsConstraintsSubstitutionsDeepInBody() throws Exception { doTest(); } From 94787a5f6721690d38e040ff5f3b192c8b97149b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 24 Feb 2015 12:23:59 +0100 Subject: [PATCH 213/231] testdata for IDEA-136887 --- .../daemonCodeAnalyzer/lambda/regression/IDEA136887.java | 9 +++++++++ .../codeInsight/daemon/lambda/Java8RegressionTest.java | 4 ++++ 2 files changed, 13 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java new file mode 100644 index 000000000000..6015c09a1c24 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/regression/IDEA136887.java @@ -0,0 +1,9 @@ +import java.util.Collection; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; + +class Test { + public static int sum(Collection collection, ToIntFunction mapper) { + return collection.stream().collect(Collectors.summingInt(mapper)); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java index ea3d7f543801..e6934f2715e7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8RegressionTest.java @@ -35,6 +35,10 @@ public class Java8RegressionTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIDEA136887() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From ab8c437a3333a41dbccd2bbb3f01f661129dc87f Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 24 Feb 2015 14:28:04 +0100 Subject: [PATCH 214/231] method refs: simplify if first parameter is a receiver for method reference (IDEA-136882) --- .../LambdaCanBeMethodReferenceInspection.java | 11 ++-- .../intellij/psi/PsiMethodReferenceUtil.java | 56 +++++-------------- .../PsiMethodReferenceExpressionImpl.java | 3 +- ...eferenceTypeFromExpressionDeclaration.java | 28 ++++++++++ .../lambda/NewMethodRefHighlightingTest.java | 4 ++ 5 files changed, 54 insertions(+), 48 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java index dc392cec131b..eb9f162a909d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/LambdaCanBeMethodReferenceInspection.java @@ -263,13 +263,14 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (element instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element; - final PsiMethod psiMethod = methodCall.resolveMethod(); + JavaResolveResult result = methodCall.resolveMethodGenerics(); + final PsiMethod psiMethod = (PsiMethod)result.getElement(); if (psiMethod == null) { return null; } final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); - final String qualifierByMethodCall = getQualifierTextByMethodCall(methodCall, functionalInterfaceType, parameters, psiMethod); + final String qualifierByMethodCall = getQualifierTextByMethodCall(methodCall, functionalInterfaceType, parameters, psiMethod, result.getSubstitutor()); if (qualifierByMethodCall != null) { return qualifierByMethodCall + "::" + ((PsiMethodCallExpression)element).getTypeArgumentList().getText() + methodExpression.getReferenceName(); } @@ -324,7 +325,8 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp private static String getQualifierTextByMethodCall(final PsiMethodCallExpression methodCall, final PsiType functionalInterfaceType, final PsiParameter[] parameters, - final PsiMethod psiMethod) { + final PsiMethod psiMethod, + final PsiSubstitutor substitutor) { final PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression(); @@ -332,7 +334,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp LOG.assertTrue(containingClass != null); if (qualifierExpression != null) { - boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(functionalInterfaceType, containingClass, psiMethod); + boolean isReceiverType = PsiMethodReferenceUtil.isReceiverType(PsiMethodReferenceUtil.getFirstParameterType(functionalInterfaceType, methodCall), containingClass, substitutor); return isReceiverType ? composeReceiverQualifierText(parameters, psiMethod, containingClass, qualifierExpression) : qualifierExpression.getText(); } @@ -422,7 +424,6 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp if (lambdaExpression == null) return; PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType(); if (functionalInterfaceType == null || !functionalInterfaceType.isValid()) return; - String functionalTypeText = functionalInterfaceType.getCanonicalText(); final String methodRefText = createMethodReferenceText(element, functionalInterfaceType, lambdaExpression.getParameterList().getParameters()); diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 1fd4e786509f..b9cd4b2a1393 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -30,10 +30,10 @@ public class PsiMethodReferenceUtil { public static final Logger LOG = Logger.getInstance("#" + PsiMethodReferenceUtil.class.getName()); public static boolean hasReceiver(PsiType[] parameterTypes, QualifierResolveResult qualifierResolveResult, PsiMethodReferenceExpression methodRef) { - if (parameterTypes.length > 0 && + if (parameterTypes.length > 0 && !methodRef.isConstructor() && - isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) && - isStaticallyReferenced(methodRef)) { + isStaticallyReferenced(methodRef) && + isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor())) { return true; } return false; @@ -46,7 +46,7 @@ public class PsiMethodReferenceUtil { LOG.assertTrue(containingClass != null); PsiSubstitutor subst = result.getSubstitutor(); PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass(); - if (qContainingClass != null && isReceiverType(functionalInterfaceType, containingClass, (PsiMethod)resolve)) { + if (qContainingClass != null && isReceiverType(getFirstParameterType(functionalInterfaceType, expression), qContainingClass, subst)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } @@ -202,53 +202,27 @@ public class PsiMethodReferenceUtil { return true; } - public static boolean isReceiverType(@Nullable PsiClass aClass, @Nullable PsiClass containingClass) { - return InheritanceUtil.isInheritorOrSelf(aClass, containingClass, true); - } - - public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) { - if (containingClass != null) { - receiverType = getExpandedType(receiverType, containingClass); + //if P1, ..., Pn is not empty and P1 is a subtype of ReferenceType, then the method reference expression is treated as + // if it were a method invocation expression with argument expressions of types P2, ...,Pn. + public static boolean isReceiverType(@Nullable PsiType receiverType, PsiClass containingClass, PsiSubstitutor psiSubstitutor) { + if (receiverType == null) { + return false; } - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(receiverType); - final PsiClass receiverClass = resolveResult.getElement(); - if (receiverClass != null && isReceiverType(receiverClass, containingClass)) { - if (emptyOrRaw(containingClass, psiSubstitutor)) { - return true; - } - final PsiSubstitutor derivedSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, receiverClass, psiSubstitutor); - return derivedSubstitutor != null && TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, derivedSubstitutor), receiverType); - } - return false; + return TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, psiSubstitutor), + getExpandedType(receiverType, containingClass)); } - private static boolean emptyOrRaw(PsiClass containingClass, PsiSubstitutor psiSubstitutor) { - return PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor) || - psiSubstitutor.getSubstitutionMap().isEmpty(); - } - - public static boolean isReceiverType(PsiType functionalInterfaceType, PsiClass containingClass, @Nullable PsiMethod referencedMethod) { + public static PsiType getFirstParameterType(PsiType functionalInterfaceType, PsiElement context) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final MethodSignature function = LambdaUtil.getFunction(resolveResult.getElement()); if (function != null) { final int interfaceMethodParamsLength = function.getParameterTypes().length; if (interfaceMethodParamsLength > 0) { - final PsiType firstParamType = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); - boolean isReceiver = isReceiverType(firstParamType, - containingClass, PsiUtil.resolveGenericsClassInType(firstParamType).getSubstitutor()); - if (isReceiver) { - if (referencedMethod == null){ - if (interfaceMethodParamsLength == 1) return true; - return false; - } - if (referencedMethod.getParameterList().getParametersCount() != interfaceMethodParamsLength - 1) { - return false; - } - return true; - } + PsiType type = resolveResult.getSubstitutor().substitute(function.getParameterTypes()[0]); + return type != null ? PsiUtil.captureToplevelWildcards(type, context) : null; } } - return false; + return null; } private static PsiType getExpandedType(PsiType type, @NotNull PsiElement typeElement) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 2408bbba5bff..e640caf1f802 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -20,7 +20,6 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; @@ -480,7 +479,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase PsiClass qContainingClass = PsiMethodReferenceUtil.getQualifierResolveResult(this).getContainingClass(); if (qContainingClass != null && containingClass != null && - PsiMethodReferenceUtil.isReceiverType(left, containingClass, (PsiMethod)resolve)) { + PsiMethodReferenceUtil.isReceiverType(PsiMethodReferenceUtil.getFirstParameterType(left, this), qContainingClass, subst)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java new file mode 100644 index 000000000000..a0621c1726f7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/SecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration.java @@ -0,0 +1,28 @@ +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +class Test { + + static class Base { + public BigDecimal getTotal() { + return null; + } + } + + public static void foo(List list, List list1) { + System.out.println(add(list, Base::getTotal)); + list1.forEach(Base::getTotal); + } + + + public static BigDecimal add(Collection objectsThatHaveBigDecimals, Function functionToGet) { + return objectsThatHaveBigDecimals == null ? null : objectsThatHaveBigDecimals.stream().map(functionToGet).reduce(null, Test::add); + } + + public static BigDecimal add(BigDecimal... sequence) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index 810019f54bd0..dad206251e3e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -382,6 +382,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(false); } + public void testSecondSearchIfFirstParameterIsASubtypeOfReferenceTypeFromExpressionDeclaration() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From cfab51e03fa3017d1a2a33ee4fa007a8d440b60a Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 24 Feb 2015 15:00:42 +0100 Subject: [PATCH 215/231] revert to assure that inspectionFinished is called exactly once --- .../intellij/codeInsight/daemon/impl/LocalInspectionsPass.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 3a9401308de1..f4894afc9eb1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -289,7 +289,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } advanceProgress(1); - tool.inspectionFinished(session, holder); if (holder.hasResults()) { appendDescriptors(myFile, holder.getResults(), toolWrapper); } From 640c53dbea6a2b257eee892f2378a547b1de0e29 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Tue, 24 Feb 2015 16:31:45 +0300 Subject: [PATCH 216/231] Migrate PhpDoc to markdown4j --- lib/markdown4j-2.2.jar | Bin 0 -> 59049 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/markdown4j-2.2.jar diff --git a/lib/markdown4j-2.2.jar b/lib/markdown4j-2.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..65030fa0820527a90ab8d6b8068c9f5696df9ea8 GIT binary patch literal 59049 zcmb5VbC4&&(k?u|$=;$x> zDfNxB_%ECT7zhaMZ~xy=d0_=<32{|526+khxCVqlBCJqPl${`DNGi4BGF|tJxysRH zqEFm;5O^cG-5n3+mJ6TfZU55d&LE_7Xur7`3o)j6Wd};>9cg!P7BkTfQ)&rFL>3YG z=g%=mEWsH1o;!AJHAGpNU)`|&kwzfYH72sLRR}2#%}LJfC6f5MW08qp23_U)yC?md zx$&LembRyYt6}FlOh$*h-`LFPNW>@%NhvYQh&Q_7^RWLlDIg#{d&+;AKiJ<%nL64t z{@)R>|3p|?yIHxL{C@!dp`U*|>YqRt8*^7vD_isbA@T3Z$NRrXxOutR8@t&44@r_F z>VFwF(SMLM_j3Cm(zO33{f|jIx>)`X#J`UW@t=r)48zRP(}B(Azrj%d+lGX1=pu&y z8pR_B5D@i$7>tOWqp2+!GlQv}v8!vGioD~Z5R(5Tm$L~RJNSlDv{j{aGC{o$gmZyS zDO4Lb+2g{ZMN@RHU3aSB#_t#|P!tiUKah9DNKIvPs7m8`nVem>aTXSR-!DGUMwq+| z8uc5&As#VB5fHW9US|EBApisptU)8MJTwx4qw=7+7^5sSXKsYX%qelcbYW*@Ixh~y zBC^zC&+?=Jo^w_HFxym1}&~HD4c*2-%Yzu>r{Dqn3l`MhM9g5%Eej@JTSygS0W>Ky$!v;#>46YF0I^Ilq(#lMBUz*XxFRQti)SNTzH1e4SZJsFGp`xVKeQ|F?$fBoZV3L-} zWXDw-B)?h&m_WWDdNL_`h)>$4`Q*i3F!+AAK~pbLfpi-7GxT-j8~L*tUbEWy-Vr=y z!*D>Y(7pg;oNobWF02-_c#i0|h{GgGlTD+pV2(GA{I|%vJ}Ik=Gi$%US-9DbR^~&3*k1E&fPAK$QP4rtnWg(6Dt`->wQg#6Gw(4UQrP9F%-Tti5(Mx}A)qqcp#!Qwc*uKc}G_v}}_rBW-mlwV)!u{!f;^45Ktvn@VqO*HhbKl9$R`yg<8yosCtbyNLpkau=tAx;hI=dRRw~_nLjXlESvFJ=GyDBLX+N@_t z{lUK|Jir0>B*{w&`SblOmLj9}6z!5gph%VS7>!I|m+?lE_o#jGq^!As#g5Jg8Z|xo zle?gR1V;QmL&W>BK%l6N?9nVxwkJ z%sxc)1X;3tO73!eD#*>osk#s_?3u@!#B4l`#XOAeyO_)ThfSZRWm^0Yn>8sGTiT%m z#}isFj^UvM*|yDyc1PcuRu|45S0PhEbAt|)VQIu?ucyp{LG zx49oe@v;oAa`4$KHgK9>yz*}4;fwyG{?1VqyCTbUuSLf2D?UylL!5Ip`>-TB^;)Ja zs&peP@RQ;-NDU~}Y<|ekR$BBXxGOei!xD&j%XfH1IC+?1$?bp;RUCu<7#xE^YxrHX z5y$a1R<6qdZus3%Pc}bHMq4lNQ+_Y?A=@H z(reZeYjI~$#)qs-*D@C1l(A-gOT4xT=!OfN1?8MtJkZmliP$&O zTo5$4q={v-w#ck7zSo`ZLq>ekbVak-Iw0E-hZeg+T>@wYn!uaYLNnDr4%LOa8@Z`A zrcD>$;G61~heh&OmUGK++EMu%(`1s_a{Wt+?jP_UhSymocoEmgped|_=keBe3Y(cx z6ycjZ{1(*k-~1Y{r&?yNvo~AY>~}EZ+@60{;^XIU-;LKZE-bFhc&~~ld`~(_!UJmQX2**(?!0<%% z0s0e4NOTt#iaE*y3B)+;19<{r=hk0yK($*2S=a9lPoRlWd(iffo}xvVzHMUWvoluK zEvbt~YTk-W&n4`On$ghoqcw+17=@3IDUP?4O_fO}jkA;6QZ3Wz0kK`UxHo;@r_JkE zh9jckz*Li-3!Qzgq&7#;?^PyAiw6oPP3s|VD^r;`^y;f4LKv7-@378?J8i@7ocA}H zkA3K=36qGXfkKj#=wEK*orA|2f8shQnv(O;o-SZ~)BeDu+kS)50F*HhFmG`rN4R7{ zmP^S6MbL+|j7%A;=r;J)U>Hg64rMc<-j$=M`kGm@@MHBci<{!~+?t}Ej5v>huZD>% z0rilScT5WN3$!2VZpiP<2>61cgaSfSCLY}DyrW!g^U+R$L;Gt9`G*3uH>~#r%yblG zINhRT)k;&_Pz`IwpP{GG+ydqg0q_Yh&!;~-W7qdDpr)_mZ9+E6RgPGEd0xMjv7gC1Vh~x3VI@vvlRZ*`<1I6$&T5=_%}%w4UJ}__4Xc z`--MLqX8uYvWEU7*KJo zPF(=y5m%tP-DvYX^9AJ(lJo+QyQTUW_l0vTK4zI_PJhSKo49*21rK)Zx1U*PM4GDP z8|IH^a=lM;Z0$6#x4Pd}k@Wplu@BsnEl2H*z9EK>FARd`qX)Ny!?<+$f(YM1(m-|YfZQ^}1Akop zioSSkZpFq7V&11J4Tw|Ip5s)%nikDJg+GfV)v6ii^k*-B2(owun$!!Dy(GMpeS{(I z@4i&{PYHZJ>sB~UhS*Q4_OT+~mw-C=h%K8i4Zm+;j9IKFk0lfnleyaB)R%Fb-uw&| z3wGn}3`E)%WQP4d=z4bS4gEH@ePNvUk9M~c1$VoAI9oZL=g$bVBD=ClLwwxlwuIp}w}^&<)mBo$AVnyCSJ}#}c-i z@44dAE#~5<{`C>O^@{UuH%~4g%r>wK5+8(!56bE2%aMZFltPFuGo;6k&u#+&Qk5c@ zFxeot9mZY-VqXQLyM*Ufg>$9Wvi9qu-f&t{j-99ygQytepx$QK8GU$>CN{YW+;VB* zqp2Yl{rzXEH8#XfULsM%XvbA`7nkZ1&nSRu!jIl04Q3+ZHAFNIYs6^@xOC?m_+KfM zvAjp?z+dVl`j=5N{J&5raeHewH*=SNGO751=s_VQv1)dlV$5g8t(cJ0NJwGDV59zb zE`)KiWUx_!b;r%2fc}6Ku1-jBH|4qj#$7=m3#<_-6FBIoT6jkLYMMclM(Sg2 z7}{(-vn#n|#-0Yr>xI4uOVg3j94>$8vix_Yw9M|rt6Yk!FMWVogD9_ZRS)!Ut_cAIMEn1u3^i{j^M7h0^A*eVTogu5#Aaeq``4 z-Ggov_X%l~cNuv@|5mD&83sAZRFYUy2W6s(K$@0G8hKh~>o81HQ87&cx~#aW(R@`~ z_PJ=C?-H++XZ-f!+k8~^P45Lq?u@ig(|m2dT7cia1z1tG2KDoqbBkIb8@=WPs)?=z zv*k&C9(RYS#e+uBq(n`yzPCg+K4GzOFF$}+vIu=e$ar+GRq{$(DK1Z z!CbPwEK#?mdK;`bu)l+#t-8D}(Y^mJEJB|f4*#fEq;1ED!9)MG zT22T=+*y_0d4~{%F+MM2uG^3`e%ZAHz!u*k$zRZD$!0Zow0H5o-9bsumRmmk^h-74 zso|uh`=+yhS&^^p=T`aEO`_y`?Ang;&b*I%>Xbq~v% z*9PS`4&L2M`w6aX9YsN#TSL~M?=K2Qy>(R(H-}L{5ic}9bu*ZmCRqS1vyJ_YV@XER zjU`%XT4~xEOro%z?aUWdKE>NbsRjyUv-X{CPFE{k&DqNjfDBu%^72f@?bDH}%sAf1 z3%SL2-e%^3N$|)f;8TzpNIj@_EGA?oY$kLk>OGf!bPKV%3nkq$E zEOW)wPnIELbBUCw%LzRd3pE=2?Je}eYs76Rp)EEm=L3YXQ? zF60DiPgaKyae<@7F11C!;j4{;1mZ4?CuWmXH^TI*tVd>x)dM!SFd@@JFq|ABF+V-h zIedM}VZW{BU7_wTFJ(j~F&=3iai0(zv#eS>2yL4}l9p-2B^tmIL0tuTKoQ4FCe9uv z&sor(QQttg$rI?mI%zgC%vjsseFQ5wARx~F;H09C4i?sy?k>h|){YKjBJS39X8#qs za?@p9(bUlZ-~4qmavNX}B0^$f#gA}7iFZgzSktg#lt`IKazgd2u9geZ<-AXicT}1h z+NH8pZoky+wq7e(#HrPtZzTkS8MZDU`$fLnEXU+n5Qpe)NZV##b6sz_Pj|){69RQ0 zo$w^!y6zOvoJ-6($-83k+sOdd=(nQ+>a5|Kf1ow0vEQnA^9gpX5VWU<>Q<18Yo zptL{_9sLBoElWNyu{IZOXB`dZJN4Qa$62Y_&-#5kVKS!6b{@~8!SX9-E8b(EHH_B* zd!%SD0+rsA^JdMvN$KDf!H-)tw&=v8pD*xewJ;z0iJg7Cqqt-8IIXK5SQs`iwqj zXQ`R4lCxH8G5#=bx|OqY^0#<8dg3622UvPJBa(B}m8tZuJ^7^7k%p57xg^Q~ zs>#IX^PadACU`-L$YqD>p`Afe>=Iy?NcpJu;-X@XreYNc_vFZi>|)&$yQb#DxG8Wi zk)LrKzu}R0-y-?V8(>6cAh7fe*tvp|-RntN7<7#sOu1km)oa-*f8)v-)RPw8`y|MB|Kd-Rt|H-n*!;h=>VIvFbF9o~cmxD+n_$ z3<;t05dMTBYyrN$^5*)DxL!d!pTYvgJb^R?p{WhO-!0=>xE`>)hO6Eq&>th40lmw} zzdcxwNZr`v)&;twl;e#x*0Dyl74d7jp=U~Zd-rn{CMx=trE{viJTrZhDvJe&*G=q%Tak3jA0L4|GU87b1n(4!Y8_ zvAw`g($j!v!0WyL>CW`zD&rRfQ#hdul@Uu!fZxE0EQeu(cfUpSG+TDv`jplSMFbv& zE8A<@JRRdKGYxB2n^HqPkF$+LFL&F^zl~qGDMp{1F*cEr4k*~Kb-*fRbEZ{p2hU*zd74VaS4Zc4VtfK z2nosR_(oD(h0h!{J=E}Av1c-8zWHUpFgXXu(o;jUF2e0<#P-8sD)s^dmwZ{G(~klQ zn(^|B+rw6BA5$^aQU# z`1p3>NXVy?at!+W2TtlU2bEcHo%xynbr5&;y{F956w#i-Ec*rdu&j@(;oJ0$D-m%b z{$I_}mS6#lzxuXwU0V-72J7nbb=x>gakNpTQm0!kiZ#YcpA_^Zstt1AH7de;F>AaN z54;;QqB+r{1iXB1+qMrshrYRwJ=^kI>MsDdjzw-y_I&Q(;mMY=n#8QvkkZdxvUn_- zu$zxG7*ncLIWAq3rR!Atd2zsS8||T!9MLahqv(Eirje_)jjv#^XEF)->P4bJ-Q z;Y?<%Lo!;-ksfCD7>s$NJaS(wQONZsWVXxkPyDCNfLS8OJ|E!-KZLcgIIIufX;`l_{xIGw1x1JwY(15%dEuuEEXzJ*isVVJ-{( zn^5upb@@R0VvckbQ z;vL=}Q+=4xgI1TLWA^w?of9gX4k*vlS|$yM@<2#_x7+^WLXc55b^ffB3K1f=LuY7;%N;NvWx3(g1+@45SijOpM@b?BMP)<)%q!yu7NO}D zIqVz^PQuY(`XDnXy&+|pd&5xP1qVh`Aq9@ErX&mw4vK0q2*;`f4F8WibhSCwkFIjf zsoN{1v#0ypfbX4~yx#BAH%%ZXtYEe+@L49V+;DR(<2$+#RyYmp8fLCZquc?AkW;Zc zZwN*vufzdaxEW@y**%bubnFZ`8@LNN95}9!7`QAr9XL9OY`6`$D>OHiy^{WAqp5m4 zS}I$l{7n5-BIiMSC-}0ev?0ZaT%70CsjN8ujw)TwYxl)Av98rjC>;&WkPe&e>oa*; zt1$NM-J@-v>ghjwsRgEQ_Wp^6Y@)ncNA9bfpsS45Oy@pZ+RXk<=h+6bA%k-6i`{k? zt>bHH~Rn8y|;*KKc2|A$e zI~$uEW8KW&KsERm2kt|>meTgg9XRZ^XyKpizY);yQKYjCPg)^#N)_Qx%fQ22^~x&; zLgAitKYuQtkP@#a!E&wN>sV;!h=d|+9=ceZITNN@nJi_X1ep_Rj^e6U$LMy6hC7~Z zP($RpZ_W4S;I)>j){3an0^dGrGTSM(=C{v>)2^8wFPDpySY0 zu=S*2sa}rY1*BQA0VU-9E^`#601BE5?Aeqa6+Rd{V?-qc6f5S3DVIvD`H0>X&M;>y z&cn}O(uFnrxJ&FJ4e#IfCE_-wmAjDAP>(6N*p`I=zso z$jnq_NO??(f#e%EHq$)|-`Wa(kc0y{cmiCr_PNQQj3*Qk*wGzVaWS*|0N^_siq7CD zgAo0@H>t)CBJF^mbb?YIDH}P|Hm*BD-|{0TDOC25r9ELA>R}d28wxVMxGkP&8;2=r z#m%0|zKVsZ)Ylj?zJx7^Xd9?0tuYG%V%MZ$9n>{FgVZ3JnWRZ~28OFu(5W?`01T!1w?{PlZL5mO7FMLLv*#h>Y?wCyCO_k|If`Fgcod z;oE-d{Uf5i@bUG%d+zJA(|dbM2?Xm_vVo6!OQCr&ev$Uru( zh!v1XK{g%6PGEY&#vvV;!-gOoUz?C(mJ1(|Vr^w6FgNS2$0s<P7}Jyh4H?;(8x|_yu}e6Okhl`E zceH2I#D{)Nqj^QP-OY$AxQd+p>INIAid{1Ydp_~2)M8j^C1P{0-3Z@<(u8^RerPsX zU!jzMysApYrJ7F!*CEfRwVzavxmtuo_hlSpvFB>z#iTo)2odfvQ8NVAq?7OW15C3+Nyl?XSp0oONCz6QVOHAvT@m%wJW>iov|lV;7&1I(LSr z-gdC!;lr7HjBOTIQnk1*$6-fyUeB5=U#Xm>Nnu+mg50w6C^Z(ltZP!$!MdJNWqoh< zS%9&T#c@GTu4`6it@=xweW(d}^~Adq3b!0b_it*`dTr@=TxJLC5X= zOP3#Sy}gve3Oq@N2WRzj@?6@7k^c}q5cj(gh^mY0{Kj)J`CDMZ9VlL~Fbaq2-t`A& z?^7PcFt z&%$X#o78jDd&#V2KB+(OyWTnM`l+;|`LnFyuz=y4$rJcOdOc&x&gc%!C&rWbLV6=( zS^(`k%K7Bl=0yO4L-p;zb@_`sKwC?o39`g9iKlc&e1onfcZr-`=pwB%cxji(hunAQ z4&f>MKKJh{tJiuKG@II_`m+6P5PL&`yb93MexPm?;A^OO%w2m39{WHEhpL2;Wu#zS zh4PsPedUc(+ddMy{BTLi`--4W=r6y+K6ZWqQBchba@^CMh`A&E5c9?k2r{Iu8@#=P zJaz}O1EJ)ZOMs=;b>?nWg{X&JRrWAN45uc|5bG4sX-7SO)9Pm~xip1;Cejkz8aKEj&@Z7usQ@`5@B^It}5OnMjNStYOm5v zT7-{z9czUt-bJ^eK3_Y_<`%g^qa)PpFi%nx^;(!g82yii0QI`W>QuaoYy*A1Hp;`a zjM`y-_>DTZ$R3TJqE{F7P8pow2P8FqeH548E@}xRW#;ZD;=eLVTQpE^17aYcA>sdg zg6Ut%Ex&l7z0|}P)VCdHy8Dr^jD8rwK}k~(L!l6bl7>RflZA$gI)s}^K~Q8evF_gi zA$H%|qN71Yiy>=@!3pze4!m#u5m?o|-%(#ZOz*4O&CV1fIr!@H)3597>g?>iJiEwy zIjVaW00IKU(B?QXT5K`_ph24O>oFsk#>|;g2JYd)xt+N3`i-bUkfk#sNRyq=;w^qU z4lyef(Kv}{;$?>(I(4H`8WA^<*^yvy8xbnFAZc6;qdK!ZWF&=>d!e-DPH9n_ntRZB z4szv84AJIr!P9o=jDRhA&%upauw;zvp+PiZPwiWuG$K7@%=?XEFtz^l#bmx?)|x8F z5{3sA3?Y}(oGgfs0LP*;ua6b}Dcl2!%VahrfkBx);F88Lr4`yhRo5~ePK&1$ON(7& zQlEwCLW7z!y5|OAc~=0#Tf0A@!<#qWJ$s-%(|X8FH^;-9XA5|^@)B5Os6Pzz=pKv5 zeE1=o<3(*?0hr8uK!>YsK2-nc*@$0d8focP4m7^v$vamgaN?hB$Qyuw;ACn~Ol_Q( zUNg({Lq&BwfzHOZGj>7^`P-R0!G_qw>0}K2;=AIgb+B~e)%0AuNBH_$j`w7lR=_x^ zCEE(~+;nckzilwB#(!RGn2z_o_Nv2wUcVRM-MJlxyb~sPMKVQvSnFf<3LPkhdt&A4 z-(!YIVD$Wah0fiS%KFp#b;!>PF?mKas%W0r;)U#0z$|gR z6v-P4ik$DGflH{)ttw^fqQgVt*Z@*AA}(BQLFYTmMmqLOzogu^Spps0)SGuO4bpUN z-ER7xtc279fDmV}0qvPr%U)RhB8LodiUXN1orYBXMk=3TyJ zbbbb|4KoG*VqR0jHHxmiKH|_w-EAmsQV$($>EH{Lw=y4smUX2?V->v#77``mK`@pY z%}3&Mr3ltQtGaLEBQy0@{WJ;m>U4DesiPtzy4<@bXUNs>-ZXDR2UNIv3l%~H0*dU@ ztScwIr1%gvxKu8F3DW#>7*A#D>`x>k8o5RAvbo91U{AjGcBeyEnbEY6;MR9()-B&ssx+TA4#h7_%~AQtOeEHrJk_8vIdQ zP|hBjWu-BDs~{5`CQ3}=T<=%osS;%>T~KJ@W0jfj#@m{VPse?*WDd5p$DB!S2RuBC z67@F71`RGyF9tsvl8^-btB`qEM1A$OI{iMJWQuQ);cK@9KFM2qEJ(JP&IdkIpGc+M z%XzIY7=FcYS1KREkYBqGL#=2n(z~ZGXzW*^k-WIb0`>eGk;qMcQi^!J7~E(hwcKGc zTHQgo6_HG9U=%($bvT7fA?m6c}g*$0g1PfQ*029OzwO>6ob7J2pTZQv?>GFfq&{+sX@uMIG zC!474vUaS@u8b-~$uH>>ig;&>&F1eIy@=aQJao|zv{Iz4>tF+8t}9)AnQ1z`9zhwH zg`uyvIha6c(YVIkJp9AUi&3rE>8n_IN&qmxzvWhfjBQo({<}-SAdg>3)i~TAcU@ym zlW;$|U(AfC8O3;*FyA1Tp#Zlb>IMD@odN)yyJmS}d`jLJjC&ZQ@Mq3@-!N5o|L`G1 z9{rN{lJP-&e1r=r?c-ifvIoUdy@FcrT9CP)XK7m04l4QLjx0c0mY+^_ejnINDMHe? z4*?R34C50*E9@L5SQp!*==VpwokzId2$bi@B6it>r=blK{c~(U0R|T7XRyM?W z$Mb5eQ($4&$)F-{Zc&PwX#dsQ+k6mns|x0br6cb)p-GBkbSo zl#1|l_ljZqKr}W1k|%*+8Fz+*V8)sv3K6CNz6#cNzXGqjT*LQ0Tf=-mUxQC}U&7X! zw?NhIyc-mjkq!XdxF^!PxG{qTEQvFG)x;DYcU5`s*k zh)Fs^r5|gN_G*GAo(V#ji)D@07!t5k!(4aSRxwRItu1&5m zWst47fGD1bPLS{3$UNsMC;;i_P|q|*HMu*-YXNYzWO1ox&`-}Z;z7rL4Zo&jSxo7k zPvd3hr6w}>8rk`rY=NIY^k5%C^YWYC1bZjG?o3TR(q*>`VPZzdxH&hp4^uEKkC-17 z9k{d>kamV*FC*ze8)kQURsLnPO^5L&dqOfeW)S(*nUempg_FZcNZ=aoeO33XYN4XC zYO(GuuuCV>o290(g!(7PAv2q?Q!|X@)Ddk-VN0(h$6xBo_os4-+R zwK4}0W|BoO;3OSG9fRBqr{~2i2$o)6vgJ*k0ld)ADDbJ_8Vlwdn1%Q}Pl$D}Q2uc> zB~{dT2<+@jNa+V}qh~g(*;qXFHs(JRWKq0`m~pL`aIs7|=FB*hm=E#7i*~k9X0p)( zjzR?mtfmOH6nSr2l`_m8!BY*aNF?L>c+4)Y#+u}#k-z5cl2P!wR>B5@R7K&H4eJ}J z$HI4SpBHI4Y<2aWlKPl+B(a4m=69J!ZmXGD7MFGjH3va|^-2_#PfE_*mXqb~9M=d3 ziqb23iJ8w5Rma?kYfqc#y+(Xh`bH-;5^j^n6UnmFWj3{M)Ym17xu`FS$#~!QC;kCo zB({Ik28c5g9PQ|7a)IAc(HG)!PFWFU-$lHh3^44bZkDw=Dpwh$Y-OW}@OHFX?`XI; zP>^--U`4;6UR)GiT&J0^H7A!=+gLHmMccf_u`w*K3FDd8hVn_WjlPV;_*FHRe3&)9 zL<;KITUXdo_G=pm>zinsc&+Ox$dM1q309^u* zt#$C2)%VNfFCO)&uN>j3vVCS_ixjqEq})vZnA2DnyG#1Xewa^0*muj9*Lwvz44vK; zT?a{Br4DH5wbtAC7?WSSEk90F9w$%hu(Zrl<*VswtFyHvwRUH(Z}whW%|?2Z@pbpq zi<^n7e;vzzh1+~1i{}0|<;fij1a;1rU&`H*Hx;=cQp;`7siCc(+O3scPB~U%XLoUO z!Qq!6ue7=-IS5NGo5|49v74E`QJh&q%H~yGRn#8a>8P)8vq4ub7sL5n1~&W&PeJe& z|1mh|hmz=cr<|08@(SLMWHOe|3>=TU%}X<&`HL&5a5h?y6#G`vY*l~!8?bG zzRy-?979H-Y*|NU0)}#tb9^hb5`E;j;j@~CI)CcjlD?LPriN%(LM&|2LXLbi+)z7a zvOHZb|Ci4M1-gd3vQ|fsc9n%1nr2m+jA_beN|nyv%^u-tT?{lCPI^rK`8cCBJPaehP>N+Ai`l!Q&i_$>7{jLC!B@E z7*f`-tnp80toatx$tO~b)_vnYcr}~og}fiCDrIAZKq><;ohd1mg%>rSn@-b~r?EuEKnQ`$4Ebo~faewRAL# zga;xG=4!nFJckY;iZ}*_=w(a ze5^u)Te&q4V#{-5Ra+uXCr@WW#b~48=Szda4{)6g74yehji9&~>c~s0$nSU8ED{Jt z!{O|r9Cy}|gSYs(pD*IX!9C3v3~NN)0id}X(9wcRUqtx=2|x*eW)sEV0tQ}#7S{3O zzqcY2HB>mk4oV<~$sd4u0oE8)tjDo;qUqdsyMnYd;;0$eccM5M;-L$DxFc(aDjyut z0#84%Ylri9Lf?T|-M_9UxDA1SA=-*m9Fp)u$hv1=3(g#@9#<7L5|8#DeZH$#-ZCQOf6xHf5 z=mdMiC(#wYtDrz=!jzLcu(Ix1_70<>t82GR7qpML_jYqdaE`r^yDjgE^_t5WX#**P zK4Cq|k^eX4_3Hav%u^fUy&P$^5wrpm*C@GExd&-U=@8{zCCra=Gk!?*3O)#da*jBi zz8{S6m2`iG3t_2Cx~7^+e46!{JaE^VG3MxEe%HJk;pK82KG+jv+l4_B=(cWdK!kZ~ zw6Xu8sE@=a(501|YBTKxeaLmV2qjTJjz`VQjTGSw^2%{oPb)1uWm(ky^J-D|d`k0U=^N*uR^N)`rP*mgF1toq@ z2l(P8R3;RDZf>ES!t&36D)lo5f_i$ZPN=s(bCm)rMLyLWWxzSjz4<*lV9Tz9CbV}_ zXdG;UK%?fk^nY-ghcmAc^CP&{J1g9gRqmu@M%>>x#k%E~q%n(k4PBz;nLHV*mP|2c zT_rsqDo$mwr2B5IwBwRQSpOg#4+|*bJGYby`!1|G*BlEHWyI~h%`aT3Fpa)8+Ri1DBj!31#v}$8RMtMdM*Om!fh>v^e`e^3-jMshPk>m zrtu5@+-K#3=pAHx!AJ-rbOy5V!n@#tQe_5RWJ<25!wWaS3tP`f;MR&1bwW8Yp+*>y z;Ug$NglV~B>qE#4vZ-62kG4X>d z->cRNcHAF-0e0q#G=HH_J4_gUwak$oU!Ws)YIQo$n+H9O>1`J(IS^q+!i*|BLnU=? zpc=GM4sS6*Sb-*l5aVY+SJtD@Fzw+&#T_QcLeV^QX#gHF!Ic_z&=Bo&hzDUxNK1M@Y<%HB+mT6@y z^JPUt>3CGNj(Oypx4IqAX8h_{u$XFXADzyycjvZj9_Z$a*(Bi*rP{RLw@TWDV<(6M z5yzb}L~OEd-Yg2vm*&)VKhfoVmacx(;^lG!P#oJkOvVq9XWzXiU2~9U&%w3fQ_Q$a zA^}Y0wdY`9R~O|pigZ#OS=%T^B)18&X{W_cPfP}v8xG9@6j7$Zo3V3yf6CNk(|^I+ zZ2T%cxjSAaOG~%WPO--u8x`qUuMGG5;?Qa=-VW-Ha*+A48UpGVTHB5s50F=qXyw3d z>lf+9PTSLn+@nt^vM+XvZFH9DTRF5(aj=ibzE^06_Z(C;OLRQgKHBfvm$eJKbwY%( z6NS7Py73}>A}7QPL;R^I5J`C;dgO^{3jTUzx0MjU_e1#iwE7EJ?Fi+)onJiP3wSq- zAsJ(UwD&MdV>>yMhIU~p$pllhPF)DRWKgyV=H{7a3VXFdYi|Z2lEoXaaoOMQB?xqt zR(92Dq&0R|8PQdC=J%6p9I<_ZY!7f!;~7>{6)JtqlJ+Ie99(uIUF@$7 zxN!&%8P+K?p6sF~7l+~HY$Ln0Y{-W7_HYMaN`DE*Fw^rxRvXz?5zjX?oEFr!-(IQ0 z{7WF*X<)^syyj@60j!hkqwUh_Hc`wS*P|JWxf{lv+|UTKS$K^ph%3J!b!kdTO(bmw z?b1|MAYO>=4<+|T6ACc{KmZ4pZccs(ruVQ|35J8?FYIdjoGHtJu(p)}z+XVCN)`d6 zUt*BMvu;8kLXg9CPWec8?Q?tH#zC{xw%n9SZ{lUsdSLV~eJbNh&S5V;&kpT=5+7V+9(=g%>&+(n`4^mbeKJ zn#qcqA{U0#>WVEXb6j%-G?+#{50vf0HPAx7zrTG!cUIOfa!uM#HZ_mA)gfP{K#vn# z1FT}a)JmBrvLihwsdupHQ0$F?qw~EQ_yzB+d;`*+K3q^tNptUFSOo2nUHO_o0eACG zb{C{#e6BM5=`2l;LFd#C3%@RYLBBjtU(A{^-^j3!$g<|7d#%jdN{C&bHhPId zlt7dTdv{f!^Te@Z{1l@$Jf4b;`&c`a9*P}P-X)i_%TT=XM7wplHHku!9Uq?UduJ8M z@!uPDZiqSaQT#^HoaS*n;d2g3v0iT8h)6paG5g#K%eq* z_ZjV&Gl|Tp{qWb|VX{5cml?M_F;+pWJ=CY8w8)MV-V)-i{V0wTuM%MjRqHz`um@(P zf7`><`<;}S1GAxSYD@qvz+07p`RMjizGJDsQ(2MMIOFEj5QUPe7l9V4w7Q84P0y=+)xY{h8d$P%6Uyyt{=Dv zscBdYPdf92iy2#13_2}ZrKY52k#geiUylVfE;#1Nsb0MmgS5kR-NI9&@+J%p=nr=e z%!Hf6B3q0Y`->@sy%ZRSz9!HC#20tA4QPFslcC~ZVXADA1|(!}F%tXelOs&?WTVlk zCc#8A2W-rSISd#v>?AZR(GSC!2Pn>I?K(N6StC3R@;S6OWh?K)uLsr_-r{-`2AGk+vgsCOyrOxFz~_Df+_{>$-Mnl_oKGR1Qf74e|)6Z4<~QU3jDp z>69_}F7YqbaM8Tx$?dv%)HjKzk^H|&<|!D_eUH&i^1BtbC^;kFk0tI4wrB{F=nsrL z^!Z3`Q4%J$P5QP-36c>b0mnlJ(61F#g5qir;F)U#>A<#6?8>BeQCA(nwB!^jah|?G?D`4 zn-?;haDEG|KT>D5b1j-i><}tWta&Sq_xD4Bt31~g4#~OrTi|Q85PMYgVL3%P5uDXX ztE?%O9km!)wQ)nbl-{!}>aT-oJ+n|})R(J0Jjhsd>dICcu60hUSDH*jG1(vBs+Zwb zm4>cIX@4uw@W+0J;$IL?y&y34g-kn!zfQCDX`igx2Dnb$B0cCD1pqR4J5D_FUUMA- zFf(?;PCOG|`KLdAU$T>Pu6|jJgWEU<7Oq@Y=s7;&vD6$uCx+%6>;Ufi;uSrpY#}ri$$;wceNt(SJ(x| z?I^9tJZkP_NzKV_FKzUnv~b8I@J%T`X~gOswO3`6Fz5I36n;?PD2BJ$H=|fJg#{;WjO-eeaDDfWO2Tps4>*4rhUPIV|8&#SqlPAVF=a1xgmplE{i5&Qn_Nb=8z7 z!wcdRT2)w>YJJ(={RSZba_aI0KR9M-NgrZ_D{UJ6hNpTRg6&#>6@J&%{R zb1cW1|69Mifs!YF$?O9m|6O~A_-gH+AgZzLJ2d2*mowZ~gr+IZB#PBg`2xuPLtYlS zhA`T+Eamj$5eDDy3`y9b#zqjLzO;2o+Q0aGEqg1k-S?GukH?7jfro=16}lG(uEgrO z;S@cEy;X{(@uygSvK%!k>!Yk&r)H-9`K_V-$erN*2JXHDMd{y0(9YP$VBV}TSl@Rz zw=uR6DS4~j04Uk}5J;r_R1#!*j2m{0hK8EG`)xIg$jQ##)*+(Z$U7%<%BP{}w6O^m zCR61hPP2udI5~3Zpdy0{j?ZKNcfISeAm0A3uDU;1ffnDsytVg* z>DdLNy7eE6WBqC4N2Fixflc{oUj9O-JKr#T7}~@!^aWSa2oKv~gAI2#XT}|0GBU*96eEoiIjx!BHN&vF!f^{4ah!soa*M4-B%MMb;WXuP@~zpC zip5xhF7PZ0_#v(8j-CbB3O=3^4e^SixDS=U-Tk&Yx*D8W((y7cmwGYwtu=-vWkUnN z%L33-4mal12fzalg-wG4kR!*DcPL&+N5d0~rGmiPZ%KG(u~E{EllKGQdk?*vl!KJ* z-jJ&=rF{%O5r7lMJCZN-eNr5MZP0`kIG*)dX+394(;BGLO7ZF*O>0Z}NC<(cu z(#&KrT`7amwfDFy&~VQsCo|yA5#M-s!`ZqcC5TJ~>I(_wUhIPtUKy zjgIE{M9xKF886dU;0g4c<%|XA#LvM4+Xh%f&Y^kr=nxiP#RoEw_S?U+Nb)09*oK)@ zWPFEjQ-HBC`f0b`BsCQ=)mH4%?j_)`6iIK$f!B-r=Th-zYa8S1bmS!8HH6@!)kUP9 z-pjkAchN}n-LnfWF$5r+D7ZtWKrRR}#Y>}Q1@`BsR$VL7Q zqK0sgov+ENlo+-nM^`&*QVr%W7sr6!pTcAV-^pEy_-HPZN;Ak$Byi&Zs!j?|7BQk> ztYN?7aI;HFBw_ZE-B?oPGKTwHgk7i-nvfsCx-S0xA5_nOu|?3qt~6LNzkS310*g@n zFKxdv8j1@4rKm{H@($3DTm}5i&UHf*OX2-4DY3=Sq9IyC_EQZ^LM$}=+jms%UhawE zjHU=HZHQhlG7^$d8C3=bI2f?UZU4XhPq!F>z;18vup}Vh>E-xI(A&%EYMR&D>gpo( z$JMqqj+FC*jZoeA*MJj9L^IAKab%dEoZ=Q0GA!6)Fs9)!V(7yR;WT0hqzOqP zS@A5;rcA>E;V&@Ob-tc2oBM~3eUCQuG zR3lLz%w5j#Rn%<}AM{b1g z(RA>dTr~t5-Bl=>L^S~#^(vS}cJVbRny58q8hDt+bfU{pn)(`1#e4*s{2J0lc8O;) z8iXo@5ob0UfFieII>|$+Wz^;7D!$^|qO-Uf_?m{Qp5n8F8t9sRl?RDs_~n}_ztXd? z8s?gys@GDy;4=sf>Jq%4XA~M?Du_~^Y&E1+N}`^0HN{nt#dryJ5H)NXXO$+~2!$yqW66r^nW77619 z$-ZQFlCxO6(gy~~cM`MM-698K$*~elSh^(4eG+vMWM9{q-3kY8$@CHp7~OIQcDAmH z4Lw>~&2s(pLdssg@MQSz+lRX12*}U@Tj!@p;o{96x{E{yw}J(^8b)B4YnN zvLt8nteAWX$)>hTJP9INw=rYssUlfOxnlfCJgq0=6))s^Dfw7APsqDos1j?{UG!kaqDp%RUF$}1J+40D4K?_OW z%cn(f1Rq>UJojB3WIJF|!gPcospftsnRCQDD9Kx=)Ea&#WK4$FKHR}OyfJ4Y>9|

    )3RLfgtnT@JX8*9%MwIrAO z?q5YK1SAT>jN#;!TI0GEuvBaoVL|I~q&IiZ)s6n;;NNBGN`0*rV~H+RS%81pFuBm& zniFsH`_#gT1gkUlY$VywU*{pYiu>euWkF}>c3{p-5N@lpa4&BzD|Jw5UvbiYQDj>B zp=}cZ53`LzZ}+?_yB{8-GY64;_K?Z1Xl>tCX7HH-2H-Q>oP(}=;H=10Za<#QqaDeC zqm1tEtH|1;EXhS&g+R*Wx(G#jYlto^{b8)gbi+*h0up>#YfxNg^+fjZbXr6KoO9Le z->jjw?0r~2b$R*|MdmaU5Tqyo@;w(Q#~5s4$7|^uIx7+SFeLNaRfB~MfbWha$-?%> zl;hwXL;hh_@Hd+v&mxR(;H!676xe@EjNWu#?}CHuf!E>fM(7AylWPHmeo*r5qZH^ZWQ- zXo#VB?8cEgHSfVBz1U4KbKu6|&LP3r*!m{TNUb&Rp=Iqq#x0dsxPZX-8P8Se!I9Bn z=9v&tU{|;bi{)o#%ML(yPsv7{I<8C8DRn2i2AJ7d$CNX8)cIBF{qnW1n>gev zI)bU!5TzNdSVC6pUz93ro9A}qAxfO_USQu~AIfdQed3!Sa&9ZhX#JsN)20TH6RVpgy$ASydx*Jn}(1b)j6?t(mB+mN@dLu{Dy7 zZp*%u{Tm27ngQ*Z+>S%|d!mD=@3t$+)BI&~=&JTF0T1^(DAs9MIMoS|ks&k~bteVm6uFqQ>*d zyrUh^Wm|qtu#|~7W&(O8uTa-XThuKw$NR~8B_CyC)q{oo9!Rw_z<4ktiEhD-+2NJ~ z?VLkEm5>VV?UQNQsv>}qwFsW_hE3Uldt0HJ2ddwS(gM$3J$hD{jcoycVPFLR1{jQsRmG?&Rx zzlSpWf_dPr&E?p_801`E16^vExofE3mpM6&F7OLoA4Um&m#=NyW#}8v5KEkvl)tX2 zLwlyAmAlJXw)^T4Ev*|E-nWr8Etb4OX@YBmF<^l1q(I`)@oiXvGXIJ1^q&HE-4~)U z%5;N;)g2i2*4|4FlU&2{7|uT`b^7rP`$#wdtq^rsrKp=}@*+H{GQN`$&O>emyqXQ9 zkpg2B*S6m$whbj>1i~x4ew)e?GC7_WE{(8)|RZdJe+n z<&SG>Z`}Gei7cFi!F!Gu`wSyAde!kiE;(=Q6ek-SW=gb{+t)Qz40FZnYwg{un|iRS zt9m+kqGEL2Wn0Nm?TONxj@0p2w3ag3gOSV~6{A|Q)c9A(_(I#WK&^IsDd|<<_OOJb zpvVL(M|nUKkrdO)NOf8}VYhB#Q9|A2sm=;{HM%|YZ4;4XzHVX#QyoA>TMOIMoU#0> z&gpCjl$>BLnBmvrRbo{4m439dKUiIg1?u#w8Lv1kCARZFSYL{Q>m-(<>-aB3*Y(?w zoZon$**oL?21P-&K9;BIzRjboe0sp0f8$GkfWVvdBSSPNlo`=gESp0E4byFIV=z&lsL8{vzi(}`NtSwYp9(38@vBex|ur{T-@RADkfD}gZ9M#m+fal@#12`HnhUET zrH+U;JX5hf1pKMq5SboBS6T)PQ)zkV)G6N(W}AWwr6F@yOa^>I1!kzdP5F*qk7!et z7Hr0x-H@6dc~^oH2199k==mwtkeeR0j_5fg{i)RuVw-4Fj1y{IMSLh{o2(1DBUW8G zV`%P))(~HhVpBl}oKwXHB>oA~5Ti$>3HcV~n#2Y~E-mev*al?h!dB?U3DJ-ih_ox; z3+}4OFqHq)XvnZlzbXC^CdH%Bg#QwAQ}GSrX)b68smHh}l?dgc1RC;bK|FNpzR3hx zkgO|_2=k&G0P%L>Iuzt5<{~Ue>l0jnCLp5>PgG(JfxOrnDt*E`RC?dH!|Eq`&C^fg z6KaGeAj=G2P@)Z?yjUA*eZo1^df&6d>nDCK&`;|VvW?a!;|y<9;tj#P*c+;SA~;lg zKd{63Dss&iNaGVGgw`iZ48L8X4B@<38R~t)KGb{Py(9Q4b}bZ0`y4!g79e8`FI3_T zLA=-*s(ivfRC(XO!~QCI&HF*~92$fcAS(<%P+|;Wyx17(e8N4{dEdLk|0;eh_#uA{ z{-J+O{vmyh{-J%%{z3a3@rm}X2NrqViS}*xFJ)2qkF;Rje!`Y#mu}|Xm4l+CrQ4Ax z&i3^@FwS;ff|wkT0g;O$quV$8=kQ%$HaAb(A5eDgtmMkM8#phcL@QdLt!&kzEhedR zGhdp6IkuQJ@Hn$eqM12@K&a+a9LhY1IIatNDg8^n9M>$aOctb7tCaZ!_CnWiuWsDS z_FnpZnOSrxXfNu08YShi`Mw|=fQ>u)NV#IQS`8+!Vy#|KNJ{#W$(&#cK5AYzb9?04 z#+zHp+Q=o238XoBQe()L>eO>jDdlb0lQti=ioDO`XaqQ^R`k+#WxlMoCIA*#-5=#y z-tW$_y}F&Ty}E|ue(=`gg7dt_p||npx|Vol$Ay5(aj0$Gam|ysEG@#?H>P-WbEj~{ z+qzR-;i!4{HD)2lRE#j=O!EZdc0ujwtYW?8KsLm^@nn!Ai_{IAW!%xjB+YTeB#&aR z6w8>6`jK|=%w=3N$dQ#UHmXVMbRiRW-=li^#p5!$aLhhaqCW?l)Ew-Xt~7F$%$%%} z!5q!mE^eaF05@ehjCe`X>!5)|0Q~H#l%8(F;^zxB?xW`SD-TO7Bwy%y0N>2GRWcb_QRku5jtk-ap~ zb8J9mS~xP=E$^#^W!_(A?#t`s-o@-gglSx2G4e@|wA)?o!-Z?yRTTHB_d-NvS~_sA3ksEHttgB&4g`Syul4zX*>Dsn(sNI#pO|`2S@C#w#UY~c4o-=2xe zy(TiW>vfD`G9=rq<_DRA$_>4|pUxJLhPU3Kc8Rv;k~8 zK7(F_qyZwm7f(V}LrSqx96k}q_D|%)(mrFu(!Nx~fHqs@J6A^`iU6@(WVphmtD)h_ zHo(=f?d5>XbDS45hEVO6-gBOpF+)H>6jMM*B~w81SIG8a!x|rfD?P_>al;rdAB_yJ zw)GZXdpb6t3>4284s*BLR-Wqz2*LeX87mz2Zu8TBX5z*isFZj7F$h!)C%&eocvr~; zT?#Lh$3_slYY!{8-8k=7zSHem2L!?VSq8?UKnd3J$#M{qyp$Bc)K+kN}5xg9~aZ@pgaSf9m) zkenN&{Hp_%=^{wROL8Qc&UTc+0h;t70z&q8u^U$rTJ2V7&#xKj5Cemj)FI3+ys|s^ z22NGombPCZccgK{SJ<)Wm<8r9O4(R21qNV1?BEI#o+qJN>3xt|j z_Ns>2q8?Z1ttXL0P`=Bi*GYCqT%F)tZ2f*GJ})jjyOz_KT5r))meU(lF10t0TmO86 zew0vpfUd9;^!@txKx#&nrqf2|l(~;2IvSAlOmW`(k z$d9fv!PQe?T3d^CuUBYVeG`{n>kF@!%?8H>6^C~3*R($aHlOMgb{-~zbk;epcIWzt z#^=;=BD>jRo5Ss6lo9%Ik`Wv6Q*cjs+89Ds2Aa>Iu8O<*V++I1ah4H-?Eg42urcxJ zV-qYg@M>dT@$6$FS)_67W9i~OB|XPpOV%9<%^hg;Y#bQ$h7C*|zBmzGAew_9y&+td z85a0I>$ni)lgtKf#*XE^yKI>}l2^#%m=?&Ux`CpM+y~?fLs9s@|snG9~ z?MEK}T?LS#>Oqvbp7DLBHE{3W|HWEZ>p>LZ`@+RneG$zW{~wC3k`9)RmQEi3U3*=D z_Q+kv9lJS}YYFU6$?bn?$=~IPZoRnRS&UAlab+=;ZE>JqaVb+KH3fn}%7v)GrK!o$ zmZv4>ijl-NiLaUd?I*n;6#Mh^AeiSedHUVWC+JnaQ0Pa?Ve|2?mHcmXOQ$a|Riu!1 zRd^Yd3I%vZ!TL)u1!(b%koP9E#Htmp`21?-^!#$>`22e2{QOep(E1I{sf4wz{QAYs zv4oYb(ELXGN?xI3h7RRpTNe`X{%f*$Pc5mOSLT&A7gm*an?Nnw3)5OoB9ls6fpMi( zpP%`~H!S?>`>0+SW2F}k@qjg6Jpc7>yu?;cJmsc4jslBgdx24=IiDQEsvCq}nSEWa z<}r7N`mwtUw0P{bay;f1Pdw)4DGnp6O#8m!hB=>fM7zGRh9#eT!}1#_{l*)rUcG(B zN0j)^b*OmnHF3^u%T=2`08zz_kbl=0^aUy&af`Iwg?Zw_^G`(Efayq1Ayaa^!j^cv z!e-TY;5t=2^O{vW^Ey_1<673(>V;ms^O{z?^Lp2qw}Y6uaPHD`fub#e$p%M|$*L_R zSADt}yWWeAGQDu_GTpC+Rk|oay;=jWFfHE;sd^6oIIWk9WDMed3uqol8e2sA0nfW5L1Q+`-1|r za&dvHQhlAvPtTluYXc|#j*HUQ{QTvL2RYEdIE_h*d$i5NEbjq^<|t_A^)Rv=g2HdEH!#EY?;J3Kx!1Sh18*k2m`|s1}5FdthxhM*;do!@;D(OOzd<9FgQyu(#5^hW*{P=6l ziF2iP-z(4Kip^tb)q}Q(lhQ?9(1Hi79pQ&EF;@~SGmWaHmHSN0Ba02(KTrF@94LayU)dM9MX*Tt5Oz>@A`fb z_+oq3#Z#8bw??~g^tXIy9!|iX=U`N%FEt?6Bc}tzCys7O0BBLu<2{*Y4Ok&tPX2+IL*^O7r)m0|S-?H{ ztU`%itzWb7aR_TuFMPwNv z>l=J5S`g(!bmSX;tXcr@dAt>vy@LRz3Mk(Q%-kUWTLpkO0>C>kV5|W1P2cn#9I#fP z@uqL~4honn;C$0JbB6@%75ID82fX_Zj1qYB5!!pnIz}&0_7&QH$vcKGVD=sOV&EO) z7dZP4?5_jw1cBcRh;1-@FcK31K=hr7-HF4A{ds{G0Z4%e0ZD;T0YaBrv8cj<+7o_0 zG-b+D#fA2=`yy|H{P(mHZneXqzq`CQDpcwZ?theo1?`uon_+gaUN_E@viqM6!IC<8 zJNdqX-oByx(m8;NBz}!pHo#`?8taN@N?-L)f zx6p3D!b{qn?J@hTbv}@{(0gDfVE!fL&hnUkRy)6u*VubtH(>E4SH_5|$-jCT} zc0l&|w7Z@4KYEsV-%6n80p$w5ev`vbgLY%SRxm9VG z)48;X&P4&<>RVek>DLqe5r!x2qtqqM+n4&`oV%e0515H=%4#E%93VV%s3XVSpPV8~${ z%3#QQjHjQ_nBG$G$$G4y8B+A*Jnr|%dU``YCY{-W5-%v1HxA?CJN)@cD=he&=u&dpwn=5KH zB9?d-747<#AQla4)a*)5NjYWhT25&>CGBcXDK#lI9sT4LQ*)eNWoD9cY+vPOQgR$$ zWoMFe>|f=VWoFpH%Z}t3S-{J&XapBc64+VW4+v$BTd*GgR~&-$go zX}9Y0vQI}X8AE2zFj%=Q8qZW++IHE=98I;{@=x=#awo1@Z}rN^jwkIkRu77OX#MI&j21nsB5% z+Hgd1V%17gM`cP{M{P=CC3)wUOF~bqSPM>^RAuj*vLx=?vc&FNs>uBG706$8rb%A) zrpaD)r%7M+mr%eNj?lpwvCzU8u+YO8Gf>1C&VCkSO+}kxiJEnd(wT*i+Lin+3887% z5l_=4P>O5gNx`v1C6m&Z_{oZ;TC!P^jbo2WPRF1Z?TQ6!)+ZU0Wzw8b)i#cT&e-ys zBDOSo0t-Ky77Ku;&X_=5!=OY_!>B}6p_?bC(8-gZW$FsWy12(+mNB~i+acCHniuOB z)tzyc+Kz#V;z-v(V!E>{OUJ|&ws~%k%`AEJ@V8kk{ZGAE`e;flZB%*22C6fL2GR^& z19^tdt^^%ZS3%Uau4EnC=4c(u=IpA@F5WI&yT!yo;Q4%f2Y1XobW}0($JUB6qQs9w z(_lVG@MR~2+nEuQKfE}5y%^$w{;boT$RmMoti!_JDL=_o&Js%*l46rX;92Ngz@?x& z7XLsCJ-zuB;ZY!cGXGCJLwMvN@%9(&s~h)!-}zUtb^31rbh$RXPugL65K#Evv;`Ho zgiCPNZ!lE_D(+u6m@+isFs9<6C>l;VvTPLKsq*aTBD5WC>!2RY^Q|J0qO|H5r?M0h zy*B-GP^`Xot*8EmAN|Vm7QouOw|7gk_3z7Z;RHm>Xy9YE^{n^6#>=+*fcvcXXJLTf zEknCIT_}>$3^L%w%Kr?-}8cWc%|W%>GfCZiiq;b&z1N}yTO?Hk?tut1v>pgy~UW4 zScL#w4(Y5qYV)}R8!~1ej^J^RpQmKR^>CoJmgsiRR3Ig!6y&RsDO7RLxP`Oy=t>Dl z3joGbZ}Kp?cz8>G^~AeKiw&)~Sm%Ygi%D5@A3_2;h z7)JTAJjJMdNLXkS~^_n`a8SptmSDy3j>@QSR1J4Fpmz5 zwea4NUE3E3mp@?zdS--1O2xVUZq1`spE@j$f~^j_So3H}c0oq0y4ZVa(@RsIS_C>v zyH{1Rt`Rf`d$vQ6uR{0_gF2ySbo{f56fjB0mnxX5Yq)zjH~TC2*U)10hO5geqf+hp z&3AvA*bPOV4d0}tV|~`X{4I-9u|7XjX(|_7qGQnm(f%a2;C2Z?b;PnLq%@Ot=2^fy zQ*D(Lr%l)I@#8mNz8oTo&{r`W*H31daf(;}GylTbY?4T~h!s69<)$Z*_s9 z3hAEMDVgbB_$j9_4uCf)$UhQ)g85`~a~3!Tti^G08{O<;`z%MTUdt030fe8g=_NLw z+mW4jxcg?j>~8emXQQ~&`yx6ab**d8NBDg21&1(U zJv&B0^;zZUJ$g78vCDUGcJR2K4JO{5m|@+J`@fy_u19;x3+03;@s1 zbs<(-+zj=*vQze0%=NYP)aQC`51>dXwruU?CGAy)e$wXQ_8O;jN5%OOZ$O7xV-km%9tSfNl){UN}9V`fmy zd=I60%nFa@o zq*JP8*wAI9GJ9rt6ae!WY0(%}L2jhP4PuBSW z(o5f@Gr|kMX@jhnv3WzSx4vZq(W`gfiF^GL(QCt^lmF5yvtu-9IN!&yP<-zi>rL@; zj*t*jNjhTcFCCvJ%;JYt@*hp1Z;86QaU+YzDbM5nLDs?st`_V58ow$l)yIZ@m$~k_ zSozW`z}@p}>NUu@tAWBrh#KpBU{ayp^3t9Y5Gt7L@V^v%KoMjrlF6SJ<=q{{VBELq zgYk_|L<1Y0`+=Jwi7woq>BMaR65f1M{YS%~N23DSq63AY4!{V~1PD@MU38d+yeWda z7)HIziIAt-dFb$Osvy>#M~V(na&eWGeK6whRjEJ24Gcz#+*E^T1-(!KR?+CIt}AJl z3Qm0I8r;o>GToj!%G8rZn}~f#;OIUv6++O;13b-{ce!dI-l@ybi@y#S6g9pB{G__a ziqiWEg3o=Y>J2Xn04wFW)>0)VnZ%W!(YY z@vCz!Gh?nPf@h%-337m{$}iDUCHs-j&GFj|L61bCC}6@xqsDj+Qp#wW5V6x&0JiQE zVI?qC=f<*iCwEAVnV5OL+gOU#NEFxT5c|en;!a)f#1r0_m(_wC(DOZY5U%G6jNSvA z%27e7ew;0$H#Cp)*r;F28Wg@hOb5`1bo> z;_rXoZ+^(US61&!+h$dkv1C@TWLEy?0JgHir>fY4wTh>rui_U{%d`?-nP;(8`7V3v zyxc)AqPu(sC%gdSGQ~731mYA=V{?(NvlY(&1bkCpc*FjJewFJ9*xGE9 zC@eHc(&P)S)}oGx$1~tLO2I;6VMp3`U-_8DQ3!7lVsJ8gH4^H>I`+_!!fT2R%BTS^ZsG(6L8|RD@&sz*!KB1X-gI)dTmE!LJX(^W8bhEO*;|>$ z0HftC`|JQk=47s0b{{q7ZHNIa@f4VO4+Do=`9haiOR`*o}TlT2maFGdDg9C0uMQO(3 zPP|fC3s`m5vhR^~!xXylVzv_1b)y18LY^&1wU*!wnTj^aUmcrP4w+h;)VVJ|+i!M3 z!+;w4bQ8Ik_fvMW8d^2mL(;ZX^jP?fYL)~>g2h`~dNMD;)+ppKA&n^TjK;%wW1B0! zZRgy;`a35MEBhh>su3ikb$oLjB~n%k5s`K#0( zggJJ<>f#awOq!n#9%HEk{{c$hIQKu)6I!e3zUU2FC3bSs%Sn;68x5{n0Zk8B8cxgFr+cs&0lLT+YyX6Z~#c#zHxXWXZb)g5h z6|e{@8HGKn8rO~VMDFtm(9H&64G~-(7OpI+oi`@}8H_CU)oF?};m;TBoJ#E+W(#?L z;mIi4B9J!`E8W?+x`pgR#MIozjqI)VxDDt|OXwQpITnaSBOw%f46twbf?4|e+Df

    &uKMz zzZgA(tuxi204N4~>5wuZo7h;be?aQ~5k;D+R66Sn>zf99z_gfP-pSN{p?OEkoILMR z2pWanMP$hQQ(_bp#d%A$GVvv|>};0Y7M0i@<>HOcza{dTc)RaMKJh2s%e@8ikP$Z* zePX|Y26u5^$O}@1cLBG?K8m0CgBi-#838eiY@x`wB|kVMHY3HUzD)dVyD0v+$R{V$ zy2nSmMI?__erZ%36p}5+ICM=drsT+_SMYr^2J0&t`yz3KQLwIEdm}8%toX5SUZ01G zgx2Ez9axW;(f@I53uFn)<{m?aEuQs!&zc+F1fp%zO}_}{(Zr$GdL^M->BkS}enS7x z72<%NqKNhv+gtC;Cy4HU*{1l<3i1DM6BMYtp@lI~Ca>3+&f zbvMo%{QSIB{?>V;2u4>&;dL!CQWLpFVWndBVz8r?LN&Mpqi>SXP0a#ifM;N#2g5xY z5XpE^AprzXG>v;eWMpZESXwEP00mH3vW?;DScvVb=zr?^ziICEZJo4DlMi}t3Ul;Q zZ`KvA|e_WD~4>+$9rA@-Mt%ou8TJgeR6(DSw zyk~D*_*cTUWM9n5+BM(hSDK_nO@6Etuh#cODdNprv`;?4U0GhBKV{oRAroB!Zk8 z|CGzkBPjoTkYZOD@TXd}d(uB2dFT~Iq{vqq+_?4%xZ?P5q60p7^!)a4*7gjDpoX)G zs;=Hg8dzygP!{iw&?R(dxcj=JxET!c36{y0(U#eiK(m%Q6Rn}~m-6`!I}UzFyGJuB zf2;NM5%k9SQpo!Jt#PwOK|#j8zal_wMu&#ES~l^&m*YniPY5W-VzW^OFxjx#h}rPn zIBv8DZsP$m><4g*S$mh|#u~}LqMl)v__}e)ex!U)Ge-4|J%M+F6QYWr>V}OO4C^(0 z$0Kv&;6&nlf@f3pCjY$svB2rz^7mO` z%t6c~R>P|#&6aZWZ2Ygvxw+mw=Wlw7GTEAiva)&eg|c$oXnA(J_+nXi(HvINnJy0O zc+pMDQ>Lg8^o2kZ1TyOKTsE`?!(=CrjGVV-kG+&!&-ua@i^r)G-l_1oG`Jt&%q}=h zJrPod|G_6%wXy-SYiCI^*tODWZjKTxUJ=E{B_#>QB|?PSD?JI$CBF!|>$ETQ_V&-> z)Z!7ix{P_wJ>KOeV%lk+vW;}%BH>%~)iTf{GpP9OF4Rj9?dmoVgR=Ag#_xZIhB%CV z|MunYkJzNSz7(KiIy&%)v#-dm>3a+#IK7b}cz915Vlh~n5fdS{KAy5StD0W25P z(7Q<-koO&k;>vRvN=XW1Bn7ggMFQ3CSPCH-IQ^N0+zLA;XZv9o8-L7G#D6$s1NPdN z&Xjatbc{WAhTUCowFw+-)+AD!9va7{$`z!@yyv2nS@;Z%Bv*$NH_7flOXY`;j3>P3 zHGapK`1x@zUq9=Vkq=)%o*NWaTv#9z1{p;WZ%e3m0^{x>0=OPf0`T%&UDKOKRfn5L zt*3;+U&1gEepo{;IyagG(mEM`;ff2v1>3}9EJ~{Gj!;JxN1l=D976wW%kQ2 zx&P;;Sx##>+gm#Q_uG(etBfy=1Na9&Miduvh?Mj;oCI-9 zhD~8|G0Ihk+{ZPfh_}jvgcG-g$FKO8zn{7KFZ}~L1%7q49_QqFO<~c026L?t&?n|6 zo@Vg|7VnK=7#;aY?$qQ$)fzNYvdq-M zPP3eY1sxfN=pNOAeLoTmA-UuH9`@4ni{K71hINM?f^nxF!g0qQLV0uywwi6+bzKf6%|OJ? z5tsEcS>fESqhH(jTyq{#{|=HG((cvX_|jT(jO|@*;H!rVR58r zkrb41g6cHbh~TT|nJoF~^Omr6cNRnhY%Jhx-RF`X(l>| znNe?3N}17WI>JF7EoFNBN9+sHS&DT@i?58sib!Pno!#k%GlA)4rp?s$dVB3b++%wt z{VakJ(R_P;3+M(x*9niuH)Ga~QtRA+QB%Ds7wu=@*8NO~m}=xM=*@jhe>hnyRIA09 zp-nCA9T?)&ngUGEa9bv8ti|$9bI*k&dIJu75UY>6HG3(F|8sA^$2BZjZ*M2tvaZ!M zU_7>apsQcHIQ-6<&Rji_={?Ok`7l#$==6+t`O8uBY&pQRVO;-mjR^l3Q&8vVuj^P? z<8^zad9U7bnEvxvn1EAlSByQ8g8Q_~Gp`jd7=b8Kn0W&EZ`7loF4OJ|E?ESs2{_Vu zDn=2~^ zcS@tJwMw&j6`8{r{jgEiP%jnV_uBU2N{n5#Sc`BpI53Ve#A8fHfA00|g_cy~XvWcw zVWP*x#>h&_vzBLR8L0KmE=4_)%;odW#bCRD<2j`eQr#AAL_U(|6qLMt&yK{V&3AJM zK656mJ)@qZ@Za#;!FhvaRNmczRRk*dL@zATh$GRv|W+{8Q(K-;Z<`txJ}Tn)J+AHv`y!z12WoTbS!N9@XKu*Lqa|yvW+SuT-him zO!m_Fo8+Yca_v_K{p4tDkjGEws_>TOC%r7&X1q*mbM2STQ3l!eYlCoYtsjJJkIV8` z-^vwbdW(={dTB0G2Bbljw%YfiwyCdkjR!Ma{iAG1xk1Nlj9j4lxJ9YTbl3HJ{Y+FY zzq&Xj!$62Ld=iyolH%ntmXO(XA+g+eaEQcs@o+DEX&6GT1XMo9I1~^3(r_kxYM3o9 zB~(9$XPADjS(I0YJo5XEEE0sZE}1p+eKym%v9bpk(8%S!!5GUS3aB~LO<2kW<@gkS z2cY^|Ls%((ILbHXf=um7y#I_;c>_MX_gzzP2=YBa{ux~Rn!2ClvqU=uoL!IGsyz(G zZa-_W0%hfhwUKdT>1vMENe$2;Q_IHv`G2_vq$jpUbbb9T(Y~Am{r*aKOMmOnFjZH^W6-?6x&XIxTNJ=Ge!jeB1QY>DfE>Wm( z0G&0C%#!?D8`CUK)vRRTxirq-J$qMDe4(LzU@?$s%l+u7keUCRA1kgTK9j^;a4f3a zWtGY?A?eF?TpV7%cCr11m6kpep7OIk z2j(-(`nIyE*__roki6R%&3S}1eNV766C(=IibAOa4>{Q9)pMN)i7nwULG0gYJTxBC{n-$iwCZ}o5VT8oWq;~s4S8=Z7Xa}Re3`tIBO-Dr{ zzCf`PsDq^%$&NmQ`!f z`AL!-s`=8)`7XhdPBGzG zE^qdO+YW$tr-@zL(1}aq__L(aqr6ht&VXDgb2ZcwpXfptv$LZ;G8*Q~*m5SzS~;+I zfA&YY5f{>>&SH;SubDgEgK;dtlbX%EXYrE8rSeE_OI#xc$^B{sqVOA+>R$&QB>qDO z3)$p{xcY0B)HF7NVmdd%VmdwoW4bm%V|t6n? zK=jiZ*_ZqIJIT}hq)1Zkk@K+aB+yoy$bJZSfr%TjOV(9=NKulT*GbQNF*28HtL?I) z(CM}`eJQGyN1EuD@51?g{K5-fmf7y$|4bB$eY`A>{?m5G@xLbu|7QyPSE5j_2OFTS z+4FCfm%CfmPhYNhsi_na)CMV9r-M=kuOf@B2Zx~|v$%mKlbTZ&yf?tyRZOmitrAkx z^=$#G{@fo97)T7b?4I@q;(7yA0l4W;flu3IjyW8Vk$;%2KW6{w&pzef0f811l zGlBD;h9Z5QgVTEc8S}4V&zwF0tZ?!=8*%#D8t;V|_ftFaUuy`WP^alXW{r2vNM?s5 zFk`i2dfb7GU3~nqq5qGtcMOg+?$*8IOw5jL+nm_8ZJQI@wr$(Copfw#GVx4Kp4#WF zxAxv2PSxtFzPqdX)Bo;!;ab0|edQ}odvE%lbLf2#YIy%{Any?+|CgU9M>d9MMjZ$a>g{6?lpnOoYs^XyL(2Mo)*A?D`O1X znq);1+7(=pDqTB>ktY5J84lN4?2kZ_Ru_W2*|4HUn$hT*(?rf@ttLEW0!oW(NouTd zaV3_BiAg1vgzLD@CJbG2#JCD`;1~s}9tQn%8FM&5TQd$}+}VmGK1xbew(L-prc9AJ zH7dCxL%e`eB~ih%T+xQ7Ri3;LawS)2R2GL90b$%+$%6w>4&1;~m-LO63^K-{Ei`6` zoh=6ZuGEnp#SUo?0Lfv~5f|f5R4s6t98y=8a@V42rpZ)e1%Z;ToG*up>ZvnSL||cp zR@LamF-*ABJ<>kQx_(foTM{>CN?4^(pb||!%C+}jJ{DK7bd%XR9>8Hg*Y8!&#oI!* zc7|M&XIPwc4BfnWVfVzrK7Q&hkSw-_=@2I9M@lDehgeNQAYR2B5r7>{BVLh>pGV6Y zHB?t`F_j3&?ac^OJ+9ZlhIjV%wf2%x$;Ht;uKIl_nYDc9?uFS6MsSH6tZdl|Etavt zm^>A*R|^&FH!D5s9WFG=ELBzir^`1sxmpA?zCIED=vFE?%xcV$W^-RXTcoQL!~Bn) zdyOo%HZgyZl$BTr;anzP-)S0hCd1fJll|W_@19F$I1+YGO9^G~VwQ#%94hii$Jk5j zA#M~!r5>@Jq^BGK^}r>QB9;tf6HH?;*%+Y?I*L;Ab8E$EwsCsiC4L6=9Y0m@URH{h zRsp{JiP`QztQ5jt^hS0*fhiqh)LdjSblj>ZNj%0tw>d7JnvEd2Xeiu_Y)#dCph3JH z6eXo-#H^RsklVO%3E+$2X=BJ@9C0tBC2pgoF_1R?P*>70Ds&tITW1E_i3$3YpB1`` zhvRowAcG)Ab?4WttZ{YH=9zGu6h|MDmTd>5gnK_FQ{ZpQMPoRNQqef&93twJ9Y*zU zth;`+O$X9%81*QG7i(K|qv32Opa_9Y^$Jv%P4?dj*$O|#-Bo?l*l_QnQdfT+ej#uO zZ13;YUmND+p;oynq&o){e5r`>uYr{xYhp=31me`T51xNS(>k%qjK*-I8sy53mo8w! zVBN$$gDFo%C&@%ED9BWu7rAFkD$wsg67>-)Zqt4$uHJr)*ruTn>SIc~^4hFGQBHen zG?Y|wyCRY|aD|ZSugEJ9ky*1~WdW9*Lh@00T$*VMGI!N)9AG+DJH0OfQm&MX(vS?s z(dZo@4626UImH8Bj(s!M=xtaGBeOUIxPi!NRE`X`qMW#jVY7ysT(Yn_I5;Z-+V$aZ zLiD3x4C?#Ro|u2&mM^N@R8~<3)!@TMCakbcN2DmMPFS?Ps)y2=#mlHUL9R=vON*bCsXfiv|)yKDCt1YUAa5PD0cS;&oXNC=RhjtKT*4L{efjF79Y8mP5 z)HCC2R5J?m!Hto=Dn=H=-LP;4BXkkKN#Ty%8b}_qHhH6~O(@8`0Qu0|;W@PpaWKL7 z-1-K%iIFu~-)lwnyvhc+O|g{9h2~oQT7`zc;`@m!n6%fZ?v+Cfq@WBI8dTTPp4vtl zN>1$E;^yl#wrD*?4ObN%c_H0_r}n0tleW!6_F6IE1gjgMYTfOF%_>&ossM zCiT!A`Jz1`G!JDbOaQQALwqX@OxtQGm+$DWlQKrSZXX7Iv;(XG_-Z#rHmK- zE%QgZfxR+?zGvR;y#lz|sB-2)f=8vzP-87I3RD@NLBDH_km`RLpl~fKA-ARg$yTLXw-ui9Vp8J1!pHfPYl2hxT zdR5Fszd;G$=u%gwxU-kG(=OUYA3QRlwaDw8yyW6|BgK<&5JdCa)w{u5gu5cd#OKtG;JlbXanimKLoV+W zr|cswkn7%A)!BOX(u<1GW|l(|MX;Jo?1rr`AJiKJ(UXjVy&ri2p3ry zg?yhROIe_W!#`@FRGpwJsw(u0!v2|<;+s5~T4l{yg^|xNUz?DpXa$ELK%95#w z1WMMWmPSiYwV)%MxF^1pK&?=G@uadWDf0#Y%8I97?$=jGPcJZlasp<_L}Sa&)#%^B zbZVq`W=&FM@+{9VEz1U5nYSywI>Tda68`LWC$2B)BtH=&AEk9ObSZ5%*SF%9X6-kX zZ)|SC8?QMyO(D3c{K3`_i;2!qQ>huEYHXE>c0yafkfu6UnZ;UfEq~%WqXlpFB)L@M zz$Yty&bmq;7|=h8$!`N(IHrg3$*5h>Qfe76WS2E4-*hsH7A#SRT7jB}+McMwv5-;= zQmujlM?X+me4AQHu(2Q5W7GK4N&T7Kpg;(`Cu2SIZ*9k76@gzLEDV^&wEcPbRuS>9 zM~S8?N~UVTz00F?CFO;nAt@VI(){>Hk1V=VKaFBeX8_Ngm3QvNPDclnJ zcESq!V8RZ1GO?RbmTd|0RD0Ynfk((5dRiahTA5BFIOYUCBqQqDLKrp&O2iN&CSY?v zVEKS02fuoF_{0%1V2$J3yxGtuG=-sIwa8V`8=A;X0h_{stOjgSvff2@@mv+pYUDZV$2xjWKVsebu~aDTzId#E)nLBoj%me( zkTuNJ6N4nFzQ~kwB5>hx8&PupN}XPgbSt8b9|?+h0(o25_;dkt*t|o_B+{;ymPNVa@5rmvqa?g^_m;LQdGLD%aL2*}DUqQ7(j)0NYa|uK$N)sd zm&{GG8{Jgkagk%673rXEgcrR4AVSGT*){m99OLY;JSK;k!+E!fkVMQD^t&UTrQX-> z!VA{I!z?bseAp9<16E(Xmk(`9=1!YjU@#pzJ>3rz&>(B*BZl(TqdmdfjvyOHCt>&CccgDZ;T!_ z@$iiyhecq53z0r)om|fau?Xa`;D2HL%1ThGG4v$UXF@Jka%z3=)L;t9MBu}E9zhIS zp%T!&1;Bd;t>9WY^bamT-*@PDj$@?5){kd!NB>h8kk*r$_4;A8W~kV{m3a%3mQ4nY%~k-jcn zod5!?R$LSZl9l0Cq$}G`t%vm=DJGz@V}!=TVAOlt?ysv%yA>&*Mn1(GwjVJ-88MGs<#eD zx@&n4snROX*IWcpL#lWGA@Y@Lrp!{eg5x#3?{*)JjA z5fx=|;dQfaCFg&gS$f^@o@o&Z)8nv8HnFiTRm~PM;{9Qd;7Ln&1DRW2LR&fR5Im?U zw++Qn)6_Pc(l_%2BV+B3o3R8y;F!#FMV?XaE0v>Nrq?k7zrZ7N7wB#UFDuR627S{p zg3sDHYyeswqvL6X>8~L!F9vSyhca-ruGu%+SdvDVSGC|TU2_O!@wNrWh$fwf1c8Mb zUaNO6fwEpph5u}$4RJIxEjO&ypm!LPcejJ$v z%vpQBQs7SfVS4ha41Nm%#~93}k2vfF8FQHG$X6c}*@J`Ui*o#clQES(0NV$z{&=D| zJ|DvVNoRRVYXola&Gv(1*thQpS|6sU8=~(4ZMzq@Jh3sPG=M{Tr0`7n*k|5_pMPvV z;3fzX>4DTgx!RBSr&4h2gc&~^8L3f8HUbupR zd-Ig{JAB!9N6T-1`a`_0&byO(pD=xqf}`#CWNpOF8^{1f|U z3=Z=jHC{D7)rfzuhYsx_i@fR>WBF^u?B7K?eg0xj^e4mnG`S%gejPh@hIa)KSlXoY zoFWJq|9OyYNX3V!x8aRFw=llY*S|>Uai5zu{uOzb1^2-A5tBZka?d7k?!UjhkB!$n zpx_JpmmE@|+~Ae$70GsUL7e+Oe?z)xdERqHN0fpOdj5zylOk+bh%4lSPq$>ypBM?W zc!bCklsv&ZxAZ&b8MC?Izg`?&52>HmGVA;>a@V>Qs+be=IK_AL_SzN5XhwT%pxK5& zb7ohV8?LgfUdvvAHE~Tka!nfK=F;8gTBE#BEdj zhrs=URet4680-&y`*di?_`*;7O?W`}56#o-g+3Q_^q!@sNRL1+kr7w!HH(xq!?4v{ z`U&!#G_kJCm#}WwWY-n1Qp*sh6Cgjgs76-`n_3td%oIi=^76}ZOkR?B(!y;Z$lY;E z4w`t!UKrOl)U?V1Gh++U-;5I<%!*N7T46(OYzyqS09A7~Z-MU;xakWJGzJM9q`9FJ z!k=qQU-U*{Fdx_7e^Acu^1&zHZ={UMfMSi)rbg#r%bp=EvDR=IfMwop`LQ7CcEG^Y zE|e?4nkBB7YF$O^J_J@p%O15{+383rTi#_&na853aTh{Yg?SUwsJgy?s@$uovsBv= zAHuVVOoJqsmBi2<zKNE$yV zGG~9;s=wFIp(OvK7y%;mQtA|+KjgzjK19q3cOvW~k@pBxkg*;-tsN$t!v{Hu)R|#X zo0d(2pEZj7D*#!6Su<{(!<;r|NwYo4Ky(`lVQpHGaV+(OP6Xq#*7f*6tchl322+JY zj!C1%FcgaNkfkgf51@qmjE%ApW3QWeDOtuBGIn(V(g7?KP>2QrRKM{z+Iek}sIgM` zu*4y!N|1{V2ZU6_U>JKFRBz5^h1G9WF-j#cUROtyFB48l0E8Yu1L#OY7^C zy(b2jmv0`BqxMzsVwnxIQ()CGZ#l+(pS9>2^eVVw-=oS5iUAp2lE~BRq5;if$T4kH z4dGqSMoc9W0gfJb7{GeiAL1u_#yQ?=Wl91_u4CGH-XFpEUK<9XQ?JuNM1O_otZ#MS z!gGDnMC6QL`TUA7STj?woaVi9;}Cix1nUC{HK0kxK?1Jbog8-x$I* zD)BxC3!y%e`92g2&LG-J7G=Cy=n#TKC&nVw7>pKxmZ@UeterTVCCUJ#dfX^Ah6NJK z8|xY4_=q1j2Opw82T>UkMrU5v8)NX&nY%P|8MAc#8u4sc_!PhlcynY+jLyBEKj;gQCri02a~ABt#Su1sN2=#$lEy@{RJU z(SM91H;B?AT|#AS(Gd=Pb2>pJ7%0y4T1W5jz_`vbyAXC>qh6BkYF? zhuRN?8)O0)oKf?m<`2CcVxJ`TsTmz|O%b(AM2j?L5x`P9r*Jl{ZE8S7cZrs9wklbh zOzENhB(=LF+$e)psAVz(+KY@v6m-eesQm@SLxF3)r=+(uA00kwykvbe{}Qip{Zr=# zFQ2xhIDuP7u{*sH%F?d| zc>fU$?`&$h?pC?;P>rGPvFJyJBjS7oq#k)L;Kg~!Pwc*kG+yV6h8gy4A1d0>jHRnj8{5Tr()h!_6~ZojKml`JFrNF~^@=FW7etaz4}( zgCi=l81@XpW9llLD%D9+C?nh+Qq2N(4zr&H53_ETvLA-r3;HzK5t$Kjo$e?j4(V;W zJ%$gum+Gi61R^5UpUJudgzuBQq6_w4kah}VnVoqM705n*ZpoWTAg|C0%gbD~Q#t<- z@9#F|fuGGXGFxrAs5?%s>Yc(jF^jFf4a;7=VRvK6k505v=X8N*Pb9Zf^RKGL=1*5I z*9Fd$n&=A9h-*=m( zK9|TO`JR&6jzGXEh6YNqK`jheDUu)h1t}7t(iZ|?ak=v1Y?1XNw#dajZJJccMJ1r} zj4*;E^%SKCFib1@gTP1AiDq1Fg4aBQpy9D?u#fXW3#l~EF&|5!%4_Zdl(TcX zQ7^VcOvq-ace~e#=QOLuTo0;`kfH(yw0}kODGuXb1RiZlO$`WbRNWtPHB1WqYJ4`v~MarPQ zWi7Xru^&NXXeF_W`F3Dt8KUH6k)L$lmhB%*@mv_pQRLb$_5Yg9sW=+h|2M~2vlxEZp`Yj>XQLUh>bt^rO`7FsEvR&0&)I(xZT-x4A}pHk zK?tO0)M4eB;b&%Eyan?>I5J><1ZE(+*yy?|;S+1&)3~WLDd`cjTF7bGLNDiRmidcy z380*632M&zEHfD$5O<@TZczBiYhL!HhB}=j$ml$%rL)U;c+@tverCp>F@9xe)aZ#4 zLEIN5FbSQbl@&ur2>kbdliX{FpTE9Wu3m6JK)!jaASMoWj22d|mTtz3&emowCYCm4 zjIN%pcHaUGMm1L}TbKVDyyR;Ba!t|5^}EgW5MY5f{eexCU7Xu^danOh_gSA-(FhxQtzN>*`vArt*sTdPQqqDYuRt|Lx|{qKo!A|0Vb3 zR&h1KAHn{eKOOG*K6}|7!Z5YAbCW)T-+0!$7ry@Z51%s~|BrMHkd=c`qAF(P0Gbj$ zDs0VjE9t*|oDpo|t4E&5id%g zPzHO#68J!wh9edljhn_uegyWyZJFD9=DMR{y;kX zZEP_%W)3FwZgDRo?7S}<<>nq?Ihnl=$BqngMj@(9mS>1JcD%@h=o{W>Jo9~uV4U0V z>aBzI5ydOnr5E~kv!-okT)C~SQ|faB*roo*D?gE4XWf9>Du16VpBr^Q1`xLz1-q|Q zhX`iLm#Mw&h;RuTUaW&5(QMsIQN10L<%K2to(6udnJ0uuo$K>r?&V6wU$?2i1RuD$6#o@~25{bSKkzK)C5|6u5^w(yoOgi^USohuk~a!We;J zio8nb!WN>)J$+}76PCqUZxEAJcysJk=8EinQ%5FNip;v5;vpcl1;W8*U?QLo)1Rs8D#qzjopQX%#Qorf8SXAHXs>myTqh>J`Kn}o9xbY77^uFG^jPKq(& zWzR5S_)Q*mn918YQDt3gzWc!4NUEs4>fHPA80q+T&+Pj1U76sEqaO3jpp^v%p^B}A zDBWCf-Wo6S4&+uhDc^=T#Z$PvVaT*?cCHbax0y+10&5_{u3}4+p2y$VVZ94Z?=If* z)b=FByNo)&gg?C(_r?#c8p9}M-mOft@O&&D=79htb*Cv`$qT2vZ1lSAQSMn55GWfu zw9|qoZ+?L%cX3zWiG?q@-bkzwVqKpoZ=S&%$%-mpf=(iB>(jUs=4Sk7jX@s60Fb*D zd!64uoPm0_-dx(-kL`naAa^G#2g%RV4U6>+%Ym%1;b^2+Vm9H>aA|$l`6Mw-w5XW4 zy!yvt>UoiAMbGTNfMXAg%Gh)d1M=B&)^6+L^upc&Qp9BHhcFrXV?yN_xgvv{sLOUg zE42<7bA!ms^&q1SFO+4JE7er3=u?%a(s(J4IBb`z?1cH1SV`X60{NxnG6eACMudwe zt7!$xHNIHCqTdV#{n?whT5M#y=UUXtYB}syTG-3<9JUb3>{#rYt$bvCHdd{+L%;Hrs~vc71Zujyw9}U42jpds^m`><>{doj#`@B@MIMV4?P zAoYYO_EdFQ6tZnEMyDUSIlDzTw#CeC#oEaNj2?2QSGsKFhTN{&l&Ly!?#k)$u|*lr z7n$rt@{f)Bk2NY_J0tpZJB0O;qd06HyB+tqia2u^g68KJ@XQPE*o}I|9s4F-%A+h; zSgy?%r3!pMGAz%?o0WWu!FpyPx39o%-9TTu0(@Xz5fNS+;5q;v*d7=A8}n-E(%H2c zYNz`+_0-wm9W}NXcS)9VnPEEOEwd_Ik{XeoZa;SC{Nvr#DW|Gr(W@kZMO*{0%3{7- z@ffi>4&pV@_fAjh7LN(_AJdPnT4r8th?jJ)uoCsCZ|e=n29#)DQ9AbyGb(#z&kiUj zHY1-rar=ABA$LTfcS~=5;b^Y{@<-6FZG=mUexl>=%(<5cx&sPq)jku$9M>NBmnGA8 zUK*(`T~r$r-g0FT%_kdk9#1hi!n(p1m^=qVor*MjMxa!e7_1OC~F?J`eYyiy(JWQT#Oi$n z`;SN+MLL>B*&3113USpH!`==6E_Ym{HXF+qM>NkhYPP1B{n(Cib#}XYhgWq*`Ys)@ z8v`-_e}z5PONZB00`8d4PLErv%?dVx%a6*5vsy3ZCI4My2Xfe!BX3dKhh4cIJ5A!} zBH8OO3~MPhI{`c5rW$4@~nfeI(pLP4d+jOR~$Q{L$Sr<2#qe7nE-2bJX`B zA-Xi&k)!5_dHv`P!i5@|mJbAHwdvaBz$>N&Q>={}mWD~Qf+@3r8ah`kEjA=tq!TTt z&%Z`ZkHpvL@yp?ihWVagdWWQ3WO*cLgrg`AY)OaM@X;`)qhdM8=~&N5N5stB;iV=F zGH1GJV|xF8ygFHY7RgXTU<@o4372+O6%W0L4#!Hr^=x%Dp)cP@&zls!g6%vOB-9vlem%gH}f=+mW{*XW%j8 zs(yx;cD445Mf=u=kk3|)$3{1VYfP9@3U$Gq=fFLB$N^rreUaV zLAq{Z1Xv!!JN*mx6rTd!&J*7OFwRDPv_LTn5b7hq4pKDjh@?x>+RGsR0WF!qu zT_uh{QpVzv5Aqtz`&252r(dJM8<=ztx9>(_oxMXxrwtTs>hzS9=ZPx}CDn1ZAk7ajI`y8%c27cy@Z)xZ*$HosP+2F)oB^+@-0*`cTpH> z=UA&^o*iCL)xWc6n@**8{5!N{+RMuK9quQs{Nk!=y7X(zDqBIpyYNS@y8gCl7HFfO zo_JqtUTXmYoat-Tq-<)3S+ru=o5C=<0l3HFE0a7U$L4GkwU&v@Pg6j{X*;ZxKNFKs zIf-(flJ?_Xn=we!z=xI|G&E;QiW3H3?c1>yU(P;aorkO*xVf<$5EXt31O2f?0NeXK;1z z`?EcV+AVSURH>AzarWPziZHc9WKB596K#FVH+G!{Q1fTSmS}<*L=wm;R&;5_8zjw^ zDco$+XdC1T#_@cy?p}gC$JnkediB2fr&e%(bZ6j8os&nKZq+?p10CNtX7CEY5%wtBgq1R|Jh;g3nf zDR={6-f;VwP7Kg<@n6&$JY%N!dHn+U?-d+pT;6H?cR$GMdnM{W{U8Tt3&#JHYo-n! z_H5RSA`Yfz!nO`3Hvg?UjaA)q0IH(@vrpd8zib_43m(AIqbAN>&x}UjmLlPVlB(1bq;cXX zHChD0Xyqw4Y=)pgcI$@VP@$>rq&CV9T6ztsuZtoHuvmv!k}=u=VAXpEb}!l4buA+J zEL)6JgvH&|ZzfW%Ll3%cKkjrmpi%S{+7Fa;}b4aRckIQ4#J{5Tx*Q<#=ASDV4$bZJ3?QmoCfV%OY^l+f+RsDis}DwJZ_5C7o%rRQH`))m znrn^k&4BJ5_u#I9?R&Wt^RH3`^gRR|C)T&HjaY5GXJp&nLq`I%vG==V>Rlm&rc#0u z_~&Y7Jb+@hyTxcP8l}ZvQGig>xnO&FDA^_3%{l7J^5}_{pWt}3On5)0JjwVMqE3Kd zAH;t6ys8gIbQb4(55Gx~+iYT*|Zy-9`*lp(61cCCE zi;tv#H1%&xQ~O&HW>qL`8El+ze!N7i<%y|_C%qV0x{}`)-3yR?W0Xt0H21h;7%Y`u zkC{15;SXNy<^MvCwMt4YA-CXbWqC!a7Z@_eLih}!DP@lm^Ej<=#OJ58 zxRbnH|Eh>xZ-33@OiYc={f(D1Q3i8Q9#RgdX5xxd2Fv~0DQ04hbII6mH!=iI?vN7` zERQo#o~+M!Kq!6B1G`boBdmO3aQg7X=s)Td9Z`dI!(H!Soy}rjd4R8^t-(ZAE9ilH zjoBbsQeFUWEai+=nS|UX4PQpr_jZ|)B(Jae>a}pXdpic3XK`nE(0~0OeJAs_5r2~( zARxYIARxs5`;Hd#bQLu-ad0+rb#VT_-I(+@6V+9~c)!EiH!^PGXOKydC<#v{F+4;B z2T_xZ?T@tvbj#KBNfVYy+nJs~2(6N$RaG0ER{99NYhgR9YIUi^w5{1T_dQ_#2jLS^ z#os*MVOwl0AffYJ=k!~S%Ps#)&t&(P*A-2G+G{ydw$oO0{M-J(1@}hCxF}EYkrTec z`D;fUr5j(ViS{_9D_`vqHh%ufLrt8*#cNC4{Aap`WpVr>01&;4abS4##94+s|qiw|-a{U@Vh#CdBEb{GAm zvmRzAYWVe1UtMu`QeR$K?IoQ>N6h0l zm8AtfECnr*x8sP^9lJO(t|LNOiP;f-R@`(arzNxaQ7bd2+ElybXLZ`Fxh!`c8QkBq zi;FbFIL}bf zMH~f#DCPUonNsf;0>%`NG|H@FlG#|34g9GMZDcce<2qL%5B^*?(`roFzqxH>cruxb z+gL_*;5ooLmau6{jYe%fIL?kDm1uR&9J`V3Tb8_ZME1M1aeCl=CGo|M{R0UVpI~gH zAsQ#mCx#nTrTU9O&G%oaCL2eaS7QD@Y zF|DgBJl&U9?30tb4(79(Ycnxc=N{#n#!`Q59 zc()BRix7l(21|b~z=J#}Ye?0DU`VZX70QiIgnWl+z}m@KP0Z!N3sZS*=S?jg!BL@U5&+oxll4BLY3{ zzukj4?`1xxqCF5karz$)+oAlz_k13p!Tm?_;Xkqcjg+c;sTTjyw(`RC_)tT>0g3jZ z5y%FopJP){hkt6D=Va22#zfRnB@Yc4C1UDP!u-HP+xus}fA<<5Nay)8FJ}rI+)HWI zGeSbtQBw+BLd^N>_#c8SiJ75vmdO%dk$Wu4WyHel5sQZ~H$WlDU3uggHw7PIy7qTBQ-isP7}pv2_tku{Tn2xpla`7Ub1oRW03mwYh^(zpT%N^q`w-m-$z~Q zAp^UN0Zw85Py2dpxSSeUkmga?sJ%?X5^Q-DXEncfk7kMHa#fo~is;w1mb#I^8L`ch zdcGBPDmA+%R*kFM`a}l+(A*AfF~7F6fr8heRMVBqAiJtflZR%1GM_j5`7nx}lrB@5 z%JTj2_2J$Ep(Ho-vxL$F6ZC&33uL->fCREbBU7g9(A3(U_wOCMWofhPeD2)71Q{V+YyxLQ6@E5wX|QIsK8-Yi#=6~&8imvT`f+pM(V$6DP*N8kgcze(-5)lg~sC< zO1vG@y)d_ZWq2IT9HgVEncfiRc4%dO$xT-~(eQhe)k)HeVXQy*ftMUtpbzNZ~@(jV~m8wF^;&JcvmGR`y0Hj?AW<9MRmon(U63i{QCkZ>Z>3Qcd(T zq;9%Xa@h0_%X1It?R2N+u`ljhv`W2U;Q9FrLe#IH*hgx&5Oz9tGPCO#IDO1(J;^IY zK;oqV{&>)JY?!&NCqqEt#X0GNlklcfEE$KnC#6B<3rU>z)L^jGafIs4U=*6nc!qZx zGK9|>v4R7fhu|Fu_iQ+%c1w+MOI<32;Jy!O2`2y=F8NZHEMX%|1oQv*Y z`2v`2D`F405A!YH8QCHZO!c1l0q3!;=gp$|r0=6p=PJ^7i(g>>z2*q*kmr{F-de-@ zoxZo(yZ!vu#=DxWN8AX1W2r~xW8*DVOh*#O;D=`#J_+vd(Zuka$PPV2 z z5*@A2AKLe?SyZu$UBUgKJ#K}Q4ZZ(%0pzCq623)+O^vgi{AVuT_fvI9NnU^NM}oI_ zX41T8ydO#srC8UQ)C(AKDtdZ^7!?&H-7iS66RPmHbAiHycmm`kDwotpw32^D20r^* zWJtxo^@}VEf2FG@rsFO9abyT@)aO6Eu?igr2yUJsQGA0!n&R_5A^-bv6b7s&%zP)z z0w^FLB>($3O4*y(x|y0O+PYa-{a-yqu12H*`Wdz#lzXNb77~V#Ml1==iT1i>Oc$P7 z3_3{#!Vm{_Bg%JV*!V*V6$5q|x@x@FGhOY<=1T4&=wZ zHYDuaglBHd`gDf`-_F%AE_x5j3v~yf18Pz;tn@=b4ClvvL6Gw{eOP_1aIgYV@sS5dumXV!Q3oop0M!Jv$kJakVZh!pAEd&u(5qZhJ1BRb1F%o)<+y ziOLxl&V!byNl`@@Z6+QI5$pNXVI*Z)r598{Z!%KUwV9$~N=J%u$+Dz=;L@IEjk@5Q zXgainwk8jQYNvsb<7UZHR8B`qZ401eWdn4Sk;Cj_<&s{fM#m<_rkGnlv=A8*gXCp% zkfK&$EHR}{sWh4`8qLZ~+MiH&W9D5oP5m;ks%OqxsELtM$xN3mrj7W53;YqlQl$g! z!kp0HMjcVc(+)v9m%$7(?NSwD9~$@K8ktg%;ajIgbany5e+Z!*7h`3vU0zF)Xe!?m zOV&)A+UVI=H#+(zzLnB2CkHIH>5RZc$aX2~D4}O%Da!VC)z8mEE}Xq`*-*#`JGstt z1oD@^MEH{MyJ%&kJ(R?hli8xjob*_7COd`mC9-p)xw4dM@sST|={A#?baAJ5yNAgB zQq4Ebu?5(rik;3AQP!QwR8;Cow%Zu4w3KH42Bnt*<}~t=m}HJnckyqG_2A|;J+%-; zsjW|v*v5_IgcUwfu$qfHa9%$*6dbq1xwuYFz^Jtts*f$x2*g`xdPEOaaK-rn<`21H z01RsMMmIezl*tV-9r^{jzhbSC%_EyH6Rap^FC&@3YB~NuuR@l;$!eUZRnz6TLpPpG0D>sDe^vKiGY1}A z24`u?$F!}XTle)u77O<$-+8e66(3|irN!X;(;jdE{iAoPp9KC14-x?Xp?o#n(P)-` zMThmT*Nacw!?hKpH7SCc^b|yslz2n`fwoor`MM%8?xj;cI{~;HaA_xK zT){RKG<(n(StUbmNw-5u{+PyS(ReOb`sLKk$HOkn zwb<&fByCUXu}V(* z9d`d{`oN{!{trIVFiF3@m|gMXVsn;c)Y7$!tY{nO2TDx&>L2(s{VXZi7rU}FsciK8 z-m%)HpkgID0`>rgMq;AnzK@>PU^}pub}Yi0G*(J zhm;4@LoWAW{C_~_*`$Yd172WL!U8zq-bNr-!g`yj@H0YLm||J_rLBHpOgCxHX<^WU z?ON6NKBLYXh@b21i!{cTg|Qm)m*Of;&Zo6jwEfYk*qlO2lK0E}k%BL(DOGdhx@u#i zFQ2JV;F1unMd_c!&l|%4oYz^1C2eVqS;0HeM~YL@J~>A`0=QIrcT}yLSH=tW;T>xx z%q>V`pPX4J2@v`DeX-Htlr>g$Ge=L63i+#HR9iGqT*G+gNmw1hgLPKkv8;vhr#CX} zPa6MXioSXU5=CrrA>YH|R1cFkZ?GX#Ws1vb=8c*swUb|GkNyD%-D7JDlPPULCGrPC z4NU=F!An8OqqlxqVYp%bb5XOr92F56NEbUA?ZkRXrZvR+}UYiH@Jleq{ z9YENV2d#R7fOo|DuI*6`_E7#*aHff=|+r_fq%B|Kz7H82Qz1Q z#_bu5S?U$!Y_&dp^NY ziP!5gq2a1twI`Ij)Frh#G}L}*b5-qjc)9Nus;H~+PuF;Z1IBLPnAJ6+&nIW3FlvWb zT*wf4AS$l6T7jq`(lqF%xB+Sc+`*kGc|eTUq!#uY4W&t{sSRo8mTaDTLS?V1wcvp} z^10ErRrj)p;zy@Q2dRr2=?Mu>wvr9+>B*d1n@Q1a_l;-J5@JRSJ}+`{UYHpAiEi$o zRTp*9QK5Z|g~Cj0zMMOL68cvj_Vq6?8^+C9v;O7s05v>HyYRAq|D$=hdZf_Z^NrnU z{1$al{qJ1pKct=inhgBURr+*)jb(H6@qVP1*&het0a4(P_#I0@xj%q-anz6$#gHwC zYlSXW?}}hnK~_Pp<#(367V2|cK)8+Qt<7Ic3+`4%0lfTYr*BUA^Szxfrxbs$?)JVQ z95JC;?1|`)c+|HfYos-kQG~T+^Cmo_0NBG5lAaU?KG-ZvsB30ahh4}BMQdv%4742p%XBLFp22{v2{Cy%Q>@yz>c8K{}f z{GF=dY0osg@a?{&U8$NY2=Xlyd7*8tO5wR*>g1;dIzwnQ*L1n+`~z)6{ws{wquzsoU8s4pSK9P!96@z#_zJqr ztb^0Pc90$o)dR@?gd-zz?|$7v2A=d! z#Te)Rr?Rt-i>i75J|G|N|&&dbSWz!u}DdXD1wM|Nr=)?0t$o*dkrB|K)jP^jAgj2j*@6xh$uui%8pSJyO;P7p=&l0BB*a@ zRf%KR6|pZR9)CxCME4YQ>jwL~H~2%r{q$T*%6vg|vJCi;*0_+oNQ!42Gp`sWq}8X;)cJ089;0d}3{e@Dl>Wn*9~z^KP-(_ArR%W(-M+|lf; zRBo?SgQ}vgzZM#jxX!Cm#IjwZGY%56USk&7xpG2hW8p@_5xLJ}J>Ue0(7gZ*6b!$QfWIyS!*!tQb+Y7lo@PUzD(|E_ z?n&Ho0Mp_+@k6+&0=BT@M#|eL%d>+sgZKIIl$J)xmQ;ctW$Ga$Rj+!Cv_BPpRGxZe zkp(LPQK+EwDuB_1-b3uG2vydddF6;T+AsZKGR{4dDc2%uWxX{c(>oJVh))uSZ+O2J z1$^#&OojCLW`kR7FH+Qyq*j39S96A$R%IK!Zaohycdh9x-hD4TeWBvjp30(?O}2FB z1^rg*rcTpT4|+A!8970I#q^s{b%9#+mOq+HI!?KJ*^3rWOnAFo*LUyaN#9;kZe!>& zskKVLG}x*9V=|xTdNd2(W#L$a_++dP)he;=fM}G8UsA_fNcuLL*SW-Cp22tr&xSA9 z?+Pz1LTwswVkfy#+L=Zmu>g6NG*9&V%7=y8DTF+oJU1v4czcaGU&>L~X2azfWMk^{ zG^~*?qioL2zSJ>j>~{@R<9a5FzT>x25+lf-P^#FkN~msJ%x!tD3Pbuxq+HL=L4E=Ak0bApe9^u*L?u3gE`~$oeu8dYwwHKUzB=Iu9`SW0+^k$0NLZb2X zWIlQy%lULE`;EjR=N-oLMb97dpYV+F>Ok&rGvq#2g?&Uy`dm%3A64)}mbu1Wp$?il z6^RFvzF|samJ3$7dxrQ)_s;N*4LUW{r}$64@Y|OPBmIS|a{_S^=3b)sN#Kk5Wjilk zA+8XWZ*I#ON>clUGEJ5+ti0cVqu0fX-@~g6(B;(#b-%*xtV;UrIQj53f;G}->65U zGqR2Cn|0M9F2!$^D>Iqu6^A?IjwKhNNc-T39EY!*S?=M|!&zKT5BI(@yXRg<8Pix# znOEwjNuSAE<5ve{+*bv3D9t`)pEOP}BNcCYGI>BT-#$#y(3DIuB-N#SF|Ns-E$P!P z#vt0Y!HTPP5(~?a^nXXOV0e`nTEi||ySQ85xOTLQ8hrC)Fr?mZh!>mak_e@Ilah&x z0yMPCRP88L%6ei*G?FU@)XW~b^My~kWYW3YP)Smm;FMU~o#Ia?m#0Y+gZl+2Y1$9r zJisN|ZIy&P?5V!z>$mc*i*nFli23WY&4stO(eD6}rrVxV;RjW_y!Vo~a{LQIus>6U zDOuJ&Tz zC#otKrJ#-+7sk61y{wOS;Sp>nHj7eT!$(*9wq ztjJ4Qi4m=XU_w*Z-Adn2DSF4sEEv>ylG^8r5^V>smu71R*h{WeCTdxMP9}z&t{C2e z=1P|wxg#$>bMMi4jsoUV_^Rz$amUKWuvtDs*fY)MrW7GF^$Uh)6!r@y)n@43hc!Ug zD{{IuyQ&-ngzYr79+OdNNL!C2@LTcSjw-WhU*RBbP?-j#@IVd&iO7IO6Av5Tn&xb% zXHfz7mce;p`&)PSRw>wIXfqS6EkKEr7irTz41p}~e9ERk-y}i1oNU?AREw%8e*w3Y z430)9tn!F1nnpAg4)O>=_TmTC2tr3MEIgSErmTNEMlT8I8;jX3tn7;7fF&mfs_aCS zcXYWsKIc2%FrM3s zB#c<+kx-FHB0gy)12yC`^>6`ehNPC2f?b`sQS((t{lSs*d&uQw9m^J?0ZOU(0+!Jy ziFwYfx;Ob_lxyeD#e`As`qW&%(9;CPH?h1vV4*YME+*?@lMSz9nw4VM=ACO@^Gc(j zYr7S}q>Xe=tP-mohD!6xy%2tsq|24$|5Sv`)Sqo0ykJo6EGW0kn@_(nu0$u(zeFhz z^P)wRow{c#Os8pE2qZfZZ0yU5>FbQy~QjP5X*4u!er$lEbcY9ifIu z-C1zL?AmazGmTbf+*N5~)F==);M}wBRkQIT$v9{DZj(Dx`74Q*`yQ3Z8mb!U(5aj2 zwt&k7C=yLMItn9sg!<^3Jxxb<_F*K8^sqSVgeUza(5rq&`m=w64XdASLaru-GnhVbEubz9o8#-ldc5#zhUp z&v^|x{UN#d$>yQj{dQYy`|O~%0)a9PTcO-F)@CSY1tbwVxm>i4em|rdp=d7erBFNN zDPtvHhh8QlOkV778k9*$?CobTgSkwYCX^6$-)EAoE%Tm3%t~6+aL~LhMw-4YVThhK z$a-;cUgT?gqrTz~3k*+l8lD=n5LI){xe_m@EEU{EgO`y6N}-02H+buvA|u1Z zxMdbb8^^GaS47#nbR}Z~FW4mf;n8@}}hd^n^b6xTKS^Z0Cvoqt`ipV_O;+@GZ zDxRv0YG=cJ;E=ElYeSLS!%h%!DR|G|e+G^}h=~~+afsqzXY>9{PenM5FjVE&y~;B; z#-Qyk2}F@XL$!0xkoVPb*dh!_D_he8^n0uJwuv0mX1eOUZL#wo9L&uOP?##TeI|ua zY9LBsl|iK+nn3-~`u@3Sypnew4^+6vaZ(h*f`U%?#!?nB1B$J^?FXbYyXgBQy-rAM zxWAvk!cfSo-Of9)S8BA<7^XWFWcJp2Luoo2#Z5q1aQyN6KGGX*IU2i*HFAugr0cVb zLMTv4|B|Io0A)=+7C4h)3WV4Fj+Ug^nNY&!hklMRsPU{OVuA^RzPK1{2*o{cfqvl*wQf}FJn8U zV>`ufEzchWh40D7k>ef6>h|>wv{Nn&Gi5E+l-Uw`&i4;xKs%njflgGs zezGf2Ls7~<)L`amNZXZHZV@kldVHZh1IM$N>W#z#=eJGrFWB;8s!@T?GO5Jz(_-rG z@lhAsMIiN*kh<;*ExKZ(qg?`BgnlR-gvhbOL}qE|%YC%Es=F@LyLo z$@=D(8G(s%+g**tVq6jI7{YH@@{|O8j|BBRu&=>{W&+8B$ulzQ7K(@m2hFcvKaFUX zc^}$Q^|?=_g+`aQrMsBd;M zmxDjLB-ND!dX5u}X@YH*Zh%J=lu10#wKkk}(IRor{V%S=EO%I>snU z)xjw2*=f(-C2g46c(jO2?Bl2{RhaJhwP5QwEi@Nps(q1I0f8b{QpSW9VF3QaGq|Ng=XY*`Ft&s1@evOIo2QR9jY_ z>0_|os-|!o>qmDVzqPA2pS)p-c=?aTr|)#|OgR}O%eQZIOEc)Bc^=c{j4zs_OPgo! z8TtiKg(?#>ca9Si++0w5vh3KgqRzZ2pT*m8o)lujnh|v?I70bM0d#PMuRNm}kxJnL z1{>mOiq)8#lU%LaS56FIqxMzM=Z$r{Pzob?9r7~%0t$p!*weSZ^rH9#37nJE!Y3pr zY@Vy1J@1wUeB=WSfAyE;+%Mo$J+a6GSQ>kHM?#)Oe~L%%osS0&i8|CBI5#>Uy~ir% zySyrr|7n%pm2kkQFG}kwi6+jRmxd(6WlHY%(6k^*X`4)OKaq<)vSCEritMIEym}`2 zRuGsI0i#SNH!q?&K#Uqn7<3ayYg9y(DM;NA9WXI<8*JfG?Ax~4!qcN?NayY-I&E~z zBld&Xx_EQdjQF>WFa>m^tYMwSCtvNdv;vh42Ts=HA-AhcCm%kMIlY&bAa3%C_tnPq z-6cmaMWv9M3^y8fiEks#mC5V(12-AVUCQ^BpW(fEyotier4xAJIw&xOs|-lUEE)Ed z6%Gc)mw%Y49hH-ZN^)LVF8Snie@$IlU@bkB#bLb%Cw(Yl0`Fym|G6~t?s~Tp9~xY< z&$QFTNb;<6s$j(Fz_VuKd_rLq%H$c=i7b;6<~@SsCf*UwycdeYgJgMOie(hkTl5pn z-MDxCHI%|<&cLKE@6vgPEuAq*P46R^3+6B3r?)KaDcfq3sb*hi`)KP#*iEnj7JJ7= zt@cG_&LV@m5ZIbrzvfv7gdi*Y^33q!od4dm<{dtIUc9K3#)mUTs z7c`Og3a8dPY9pruz_N^uLv?}(3kw)`CJn&yz|iyaBE$j)q<=1Qta-WbZ=gzga{OwV z%7XjNSb&fEkE8@xpMj(saogh0fFGR)3^Rb%>(49G4-CBjnG`Cgsiv%SSx*3}d`Q5; zGIQiQlKGFUv9SKh9AJKrTRtwush>H1PXYQj#lMlx$0a;0?DvG~M-%=Gk^Yr{SyPNh zvcB^lgdaiHzmh;PJV$Pu^$4l_FC=TPn@6eyj6pkEiR%FE`y%hx{4wu@>`4AJfPD>P zS$LS3;GYH~x4`!h34qstpYr@njD?lyrwDv=T&(#&Aqzirt}(HEN?x7&K%2Zn{=cC0 zALL9wE#Rj9iv6F{G$zy%>QPn$kQ9LO3j81fubF-^z*fp%p+~|iFxjjr&rxQ8sS662 zy1uvfA6KSdDzLu(EBo*i8%*$13ZkZR;GS)Xv9QE{P=QyVf+>#&D>&V-vAgaLc#+#V z-C&n@w}V?*|LabUnMoj$4eJt6dP%?@Ab2DbZJPg&O#WQ$s1f1p0HDetKn6#vW*U$r zIIe0ioZvA_?OQ=pWC2u75AgIvj+D9t=#j^RZ7kj4m`?VX{I)N=QKsKDSb(ABXu)A; zkLUl}RQ{`VJ5ZgFv;Yuwa+sY4A5dsGuHeVE!P7VkdcxFzNgRN19;uIf)#I_MdQgo& zKfHlT5?LwW{~;F`CHapqSuOs~RDxSOTHm<&XLJC@S-?N&nSNQe$D=5(_ zm{Vg+wtm|n!=z!_@DFK1?Z46f!=jJL#56@5GT-(6#>6yCXshD^6QJ*NHZCk}V8)^_ I^!?NS0q6~(p#T5? literal 0 HcmV?d00001 From 0d828dab6cca2d9423d18eaf52dd3033dbb359cf Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 24 Feb 2015 15:04:36 +0100 Subject: [PATCH 217/231] call getClasses() in read action (EA-64639 - assert: PsiFileImpl.getStubTree) --- .../view/JavaCoverageViewExtension.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java index 0756d656a55a..2a7103ceb9cf 100644 --- a/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java +++ b/plugins/coverage/src/com/intellij/coverage/view/JavaCoverageViewExtension.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.coverage.view; import com.intellij.coverage.*; @@ -235,9 +250,13 @@ public class JavaCoverageViewExtension extends CoverageViewExtension { : PsiFile.EMPTY_ARRAY; } }); - for (PsiFile file : childFiles) { + for (final PsiFile file : childFiles) { if (file instanceof PsiJavaFile) { - PsiClass[] classes = ((PsiJavaFile)file).getClasses(); + PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable() { + public PsiClass[] compute() { + return ((PsiJavaFile) file).getClasses(); + } + }); if (classes.length > 0) { PsiClass aClass = classes[0]; if (!(node instanceof CoverageListRootNode) && getClassCoverageInfo(aClass) == null) continue; From 1bbb52ac3803368e10ca4e4bc630a229826d7d1d Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 24 Feb 2015 17:28:36 +0300 Subject: [PATCH 218/231] EA-26820 - IAE: RangeMarkerImpl. --- .../src/com/intellij/find/impl/livePreview/LivePreview.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index bed9f0267e4f..cabb8f3f2494 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -308,6 +308,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search if (mySearchResults.getMatchesCount() >= mySearchResults.getMatchesLimit()) return; for (FindResult range : mySearchResults.getOccurrences()) { + if (range.getEndOffset() > mySearchResults.getEditor().getDocument().getTextLength()) continue; TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES); if (range.getLength() == 0) { attributes = attributes.clone(); From eac8541542159523f76de372e994c62c40484461 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 24 Feb 2015 17:44:46 +0300 Subject: [PATCH 219/231] Access to mySequence and mySocket is in synchronized contexts only (PY-13927) --- .../python/debugger/pydev/RemoteDebugger.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index e39f45f1b3a9..fce54b4e6581 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -98,7 +98,7 @@ public class RemoteDebugger implements ProcessDebugger { if (myConnected) { try { - myDebuggerReader = createReader(mySocket); + myDebuggerReader = createReader(); } catch (Exception e) { synchronized (mySocketObject) { @@ -231,7 +231,9 @@ public class RemoteDebugger implements ProcessDebugger { private void cleanUp() { myThreads.clear(); myResponseQueue.clear(); - mySequence = -1; + synchronized (mySequenceObject) { + mySequence = -1; + } myTempVars.clear(); } @@ -477,10 +479,10 @@ public class RemoteDebugger implements ProcessDebugger { execute(command); } - public DebuggerReader createReader(@NotNull Socket socket) throws IOException { + private DebuggerReader createReader() throws IOException { synchronized (mySocketObject) { //noinspection IOResourceOpenedButNotSafelyClosed - return new DebuggerReader(socket.getInputStream()); + return new DebuggerReader(mySocket.getInputStream()); } } From 9a209bd6dfacdb864032084d0f8d12a77a719dff Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 24 Feb 2015 17:31:33 +0300 Subject: [PATCH 220/231] diff: better option names * fix capitalisation --- .../intellij/diff/tools/util/base/HighlightPolicy.java | 8 ++++---- .../com/intellij/diff/tools/util/base/IgnorePolicy.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java index 69938f66fdad..919832f93386 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/HighlightPolicy.java @@ -18,10 +18,10 @@ package com.intellij.diff.tools.util.base; import org.jetbrains.annotations.NotNull; public enum HighlightPolicy { - DO_NOT_HIGHLIGHT("Do Not Highlight"), - BY_LINE("By Line"), - BY_WORD("By Word"), - BY_WORD_SPLIT("By Word In Chunks"); + DO_NOT_HIGHLIGHT("Do not highlight"), + BY_LINE("Highlight words"), + BY_WORD("Highlight lines"), + BY_WORD_SPLIT("Highlight split changes"); @NotNull private final String myText; diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java index a2317b3489ed..8c38a2af350c 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/IgnorePolicy.java @@ -19,10 +19,10 @@ import com.intellij.diff.comparison.ComparisonPolicy; import org.jetbrains.annotations.NotNull; public enum IgnorePolicy { - DEFAULT("Do Not Ignore"), - TRIM_WHITESPACES("Trim Whitespaces"), - IGNORE_WHITESPACES("Ignore Whitespaces"), - IGNORE_WHITESPACES_CHUNKS("Ignore Whitespaces And Empty Lines"); + DEFAULT("Do not ignore"), + TRIM_WHITESPACES("Trim whitespaces"), + IGNORE_WHITESPACES("Ignore whitespaces"), + IGNORE_WHITESPACES_CHUNKS("Ignore whitespaces and empty lines"); @NotNull private final String myText; From 812692e8b02d4500dde3d6db09dd838bb57d0e7a Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 24 Feb 2015 17:14:52 +0300 Subject: [PATCH 221/231] extra logging for EA-63606 --- .../src/com/intellij/debugger/engine/DebugProcessImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 29a2c3414695..09c869db99c5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -1098,7 +1098,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb throw (RuntimeException)exception[0]; } else { - LOG.assertTrue(false); + LOG.error("Unexpected exception " + exception[0]); } } From 121781325d2939a135e793ea55227197dfe251e3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 24 Feb 2015 17:46:21 +0300 Subject: [PATCH 222/231] EA-59357 - ISFE: StackFrameProxyImpl.isLocalVariableVisible --- .../debugger/jdi/StackFrameProxyImpl.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java b/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java index d084c0308b72..cc0a18951971 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/StackFrameProxyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -84,6 +84,21 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy { throw new EvaluateException(error.getMessage(), error); } + @Override + public boolean isValid() { + if (!super.isValid()) { + return false; + } + try { + if (myStackFrame != null) { + myStackFrame.location(); //extra check if jdi frame is valid + } + return true; + } catch (InvalidStackFrameException e) { + return false; + } + } + @Override protected void clearCaches() { DebuggerManagerThreadImpl.assertIsManagerThread(); From 07a328e5bdac634e9fadf099583fdddaab0f6ba5 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 24 Feb 2015 15:59:09 +0100 Subject: [PATCH 223/231] project: deprecated YourKit agent option dropped --- bin/scripts/unix/idea.sh | 2 +- .../impl/src/com/intellij/compiler/server/BuildManager.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index 19932d440338..28b37bd39950 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -151,7 +151,7 @@ if [ "$IS_EAP" = "true" ]; then OS_NAME=`echo $OS_TYPE | "$TR" '[:upper:]' '[:lower:]'` AGENT_LIB="yjpagent-$OS_NAME$BITS" if [ -r "$IDE_BIN_HOME/lib$AGENT_LIB.so" ]; then - AGENT="-agentlib:$AGENT_LIB=disablej2ee,disablealloc,delay=10000,sessionname=@@system_selector@@" + AGENT="-agentlib:$AGENT_LIB=disablealloc,delay=10000,sessionname=@@system_selector@@" fi fi diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 9648285288a1..ceeef8a6c781 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -1017,7 +1017,7 @@ public class BuildManager implements ApplicationComponent{ } if (isProfilingMode) { - cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild"); + cmdLine.addParameter("-agentlib:yjpagent=disablealloc,delay=10000,sessionname=ExternalBuild"); } // debugging From 4942c14f994e86f10a3f5f40f0be561c57cf1b2d Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 24 Feb 2015 12:25:19 +0300 Subject: [PATCH 224/231] minor --- .../codeInsight/editorActions/XmlTagNameSynchronizer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java index 18427c96c96c..ce58b9311c18 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java @@ -76,14 +76,14 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio @Override public void editorReleased(@NotNull EditorFactoryEvent event) { - uninstallSynchronizer(event); + uninstallSynchronizer(event.getEditor()); } }, ApplicationManager.getApplication()); processor.addCommandListener(this); } - public void uninstallSynchronizer(@NotNull EditorFactoryEvent event) { - final Document document = event.getEditor().getDocument(); + public void uninstallSynchronizer(final Editor editor) { + final Document document = editor.getDocument(); final TagNameSynchronizer synchronizer = findSynchronizer(document); if (synchronizer != null) { synchronizer.clearMarkers(); @@ -91,7 +91,7 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio document.putUserData(SYNCHRONIZER_KEY, null); } - private void installSynchronizer(Editor editor) { + private void installSynchronizer(final Editor editor) { final Project project = editor.getProject(); if (project == null) return; From 42b60a7769f18b77ce6c5a76b3dc27dd10aca616 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 24 Feb 2015 12:48:37 +0300 Subject: [PATCH 225/231] diagnostics for EA-64904 --- .../editorActions/XmlTagNameSynchronizer.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java index ce58b9311c18..8cf80b20178f 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlTagNameSynchronizer.java @@ -30,6 +30,8 @@ import com.intellij.openapi.command.CommandAdapter; import com.intellij.openapi.command.CommandEvent; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.diagnostic.Attachment; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; @@ -58,6 +60,7 @@ import java.util.Set; * @author Dennis.Ushakov */ public class XmlTagNameSynchronizer extends CommandAdapter implements ApplicationComponent { + private static final Logger LOG = Logger.getInstance(XmlTagNameSynchronizer.class); private static final Set SUPPORTED_LANGUAGES = ContainerUtil.set(HTMLLanguage.INSTANCE.getID(), XMLLanguage.INSTANCE.getID(), XHTMLLanguage.INSTANCE.getID(), @@ -265,12 +268,17 @@ public class XmlTagNameSynchronizer extends CommandAdapter implements Applicatio int start = -1; int end = -1; for (int i = offset - 1; i >= Math.max(0, offset - 50); i--) { - final char c = sequence.charAt(i); - if (c == '<' || (c == '/' && i > 0 && sequence.charAt(i - 1) == '<')) { - start = i + 1; - break; + try { + final char c = sequence.charAt(i); + if (c == '<' || (c == '/' && i > 0 && sequence.charAt(i - 1) == '<')) { + start = i + 1; + break; + } + if (!XmlUtil.isValidTagNameChar(c)) break; + } catch (IndexOutOfBoundsException e) { + LOG.error("incorrect offset:" + i + ", initial: " + offset, new Attachment("document.txt", sequence.toString())); + return null; } - if (!XmlUtil.isValidTagNameChar(c)) break; } if (start < 0) return null; for (int i = offset; i < Math.min(document.getTextLength(), offset + 50); i++) { From 9c1a2f678ce2176a05431ea4d2709fc370421f27 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 24 Feb 2015 12:59:55 +0300 Subject: [PATCH 226/231] EA-64560 --- .../src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java index ae0f18066a14..b157a254de4e 100644 --- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java +++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java @@ -344,7 +344,7 @@ public class BreadcrumbsXmlWrapper implements BreadcrumbsItemListener Date: Tue, 24 Feb 2015 17:54:04 +0300 Subject: [PATCH 227/231] diff: fix capitalisation --- .../diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java | 2 +- .../src/com/intellij/diff/tools/binary/BinaryDiffTool.java | 2 +- .../diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java | 2 +- .../src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java | 2 +- .../src/com/intellij/diff/tools/simple/SimpleDiffTool.java | 2 +- .../idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java | 2 +- .../idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java | 2 +- .../idea/svn/difftool/properties/SvnPropertiesDiffTool.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java index dd0a87dd7dfc..dc0b4fae73ea 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java @@ -44,7 +44,7 @@ public class ErrorDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Error Viewer"; + return "Error viewer"; } private static class MyViewer implements DiffViewer { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java index 542ce0779bc4..a3fe98a865a4 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/binary/BinaryDiffTool.java @@ -37,6 +37,6 @@ public class BinaryDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Binary File Viewer"; + return "Binary file viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java index 4bdf3d29256f..8e5261256707 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffTool.java @@ -38,6 +38,6 @@ public class DirDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Directory Viewer"; + return "Directory viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java index b94dbefc2b54..881099ae5f91 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideDiffTool.java @@ -37,6 +37,6 @@ public class OnesideDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Oneside Viewer"; + return "Oneside viewer"; } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java index 8e450792cb30..00ad0ec846e3 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffTool.java @@ -38,6 +38,6 @@ public class SimpleDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Default Viewer"; + return "Default viewer"; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java index 99d2aca68ca5..3dd4744fc179 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnPhantomChangeDiffRequestProvider.java @@ -57,7 +57,7 @@ public class SvnPhantomChangeDiffRequestProvider implements ChangeDiffRequestPro @NotNull @Override public String getName() { - return "SVN Phantom Changes Viewer"; + return "SVN phantom changes viewer"; } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java index ed5245c639dc..35562e795f06 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/SvnTreeConflictDiffRequestProvider.java @@ -73,7 +73,7 @@ public class SvnTreeConflictDiffRequestProvider implements ChangeDiffRequestProv @NotNull @Override public String getName() { - return "SVN Phantom Changes Viewer"; + return "SVN tree conflict viewer"; } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java index 5f599aa4b55b..bf95f8694bd4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/difftool/properties/SvnPropertiesDiffTool.java @@ -9,7 +9,7 @@ public class SvnPropertiesDiffTool implements FrameDiffTool { @NotNull @Override public String getName() { - return "Svn Properties Viewer"; + return "SVN properties viewer"; } @Override From d0a383f6fb0ea15a95565b606f0c0abca310ec06 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Tue, 24 Feb 2015 18:39:54 +0300 Subject: [PATCH 228/231] removed useless listener --- .../editor/StudyEditorFactoryListener.java | 39 ------------------- .../edu/EduAnswerPlaceholderPainter.java | 1 - 2 files changed, 40 deletions(-) diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java index 912269d3b446..1a04083a612e 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java @@ -4,59 +4,21 @@ package com.jetbrains.edu.learning.editor; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.event.EditorFactoryEvent; import com.intellij.openapi.editor.event.EditorFactoryListener; -import com.intellij.openapi.editor.event.EditorMouseAdapter; -import com.intellij.openapi.editor.event.EditorMouseEvent; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.problems.WolfTheProblemSolver; -import com.intellij.ui.JBColor; -import com.jetbrains.edu.EduAnswerPlaceholderPainter; import com.jetbrains.edu.EduDocumentListener; -import com.jetbrains.edu.courseFormat.AnswerPlaceholder; import com.jetbrains.edu.courseFormat.TaskFile; -import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.navigation.StudyNavigator; import org.jetbrains.annotations.NotNull; -import java.awt.*; - public class StudyEditorFactoryListener implements EditorFactoryListener { - /** - * draws selected task window if there is one located in mouse position - */ - private static class WindowSelectionListener extends EditorMouseAdapter { - private final TaskFile myTaskFile; - - WindowSelectionListener(@NotNull final TaskFile taskFile) { - myTaskFile = taskFile; - } - - @Override - public void mouseClicked(EditorMouseEvent e) { - final Editor editor = e.getEditor(); - final Point point = e.getMouseEvent().getPoint(); - final LogicalPosition pos = editor.xyToLogicalPosition(point); - final AnswerPlaceholder answerPlaceholder = myTaskFile.getAnswerPlaceholder(editor.getDocument(), pos); - if (answerPlaceholder != null) { - myTaskFile.setSelectedAnswerPlaceholder(answerPlaceholder); - final Project project = editor.getProject(); - assert project != null; - final JBColor color = StudyTaskManager.getInstance(project).getColor(answerPlaceholder); - EduAnswerPlaceholderPainter.drawAnswerPlaceholder(editor, answerPlaceholder, true, color); - } - else { - StudyUtils.drawAllWindows(editor, myTaskFile); - } - } - } - @Override public void editorCreated(@NotNull final EditorFactoryEvent event) { final Editor editor = event.getEditor(); @@ -78,7 +40,6 @@ public class StudyEditorFactoryListener implements EditorFactoryListener { final TaskFile taskFile = StudyUtils.getTaskFile(project, openedFile); if (taskFile != null) { StudyNavigator.navigateToFirstAnswerPlaceholder(editor, taskFile); - editor.addEditorMouseListener(new WindowSelectionListener(taskFile)); StudyEditor.addDocumentListener(document, new EduDocumentListener(taskFile)); WolfTheProblemSolver.getInstance(project).clearProblems(openedFile); StudyUtils.drawAllWindows(editor, taskFile); diff --git a/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java b/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java index 49921f2b37eb..25d1783f74ff 100644 --- a/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java +++ b/python/educational/src/com/jetbrains/edu/EduAnswerPlaceholderPainter.java @@ -49,7 +49,6 @@ public class EduAnswerPlaceholderPainter { g.drawRect(point.x, point.y - 2, (pointEnd.x - point.x), editor.getLineHeight() + 1); } }); - editor.getCaretModel().moveToOffset(startOffset); highlighter.setGreedyToLeft(true); highlighter.setGreedyToRight(true); } From c36a6d30382fb1a65500f470032bd0481229fa76 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 24 Feb 2015 18:42:42 +0300 Subject: [PATCH 229/231] IDEA-105576 MacOs Lion kbd feature "press-and-hold popup" incorrectly works in editor workaround suitable for Oracle JDK --- .../editor/impl/EditorComponentImpl.java | 13 ------- .../openapi/editor/impl/EditorImpl.java | 37 ++++++++++++++++++- .../util/resources/misc/registry.properties | 2 + 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index 95a4ab25444b..866bc141d47f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java @@ -63,19 +63,6 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP return myEditor.visualPositionToXY(magnificationPosition); } }); - putClientProperty("sun.lwawt.macosx.CInputMethod.selectPreviousGlyph.callback", new Runnable() { - @Override - public void run() { - // This is supposed to be called from sun.lwawt.macosx.CInputMethod class of a custom JDK, - // built for IntelliJ platform running on MacOS. - // This is required to support input of accented characters using press-and-hold method (http://support.apple.com/kb/PH11264). - // Non-patched JDK supports this functionality only for TextComponent/JTextComponent descendants. - int caretOffset = myEditor.getCaretModel().getOffset(); - if (caretOffset > 0) { - myEditor.getSelectionModel().setSelection(caretOffset - 1, caretOffset); - } - } - }); myApplication = (ApplicationImpl)ApplicationManager.getApplication(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index fcdbe2fc4147..ea0ce0da254b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -308,6 +308,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi public final boolean myUseNewRendering = Registry.is("editor.new.rendering"); final EditorView myView; + private boolean myCharKeyPressed; + private boolean myNeedToSelectPreviousChar; + private final TIntFunction myLineNumberAreaWidthFunction = new TIntFunction() { @Override public int execute(int lineNumber) { @@ -902,9 +905,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myPanel.add(myScrollPane); } - myEditorComponent.addKeyListener(new KeyAdapter() { + myEditorComponent.addKeyListener(new KeyListener() { @Override public void keyTyped(@NotNull KeyEvent event) { + myNeedToSelectPreviousChar = false; if (event.isConsumed()) { return; } @@ -912,6 +916,18 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi event.consume(); } } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() >= KeyEvent.VK_A && e.getKeyCode() <= KeyEvent.VK_Z) { + myCharKeyPressed = true; + } + } + + @Override + public void keyReleased(KeyEvent e) { + myCharKeyPressed = false; + } }); MyMouseAdapter mouseAdapter = new MyMouseAdapter(); @@ -5413,6 +5429,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @Override @Nullable public AttributedCharacterIterator getSelectedText(AttributedCharacterIterator.Attribute[] attributes) { + if (myCharKeyPressed) { + myNeedToSelectPreviousChar = true; + } String text = getSelectionModel().getSelectedText(); return text == null ? null : new AttributedString(text).getIterator(); } @@ -5457,6 +5476,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } private void replaceInputMethodText(@NotNull InputMethodEvent e) { + if (myNeedToSelectPreviousChar && SystemInfo.isMac && Registry.is("ide.mac.pressAndHold.workaround")) { + // This is required to support input of accented characters using press-and-hold method (http://support.apple.com/kb/PH11264). + // JDK currently properly supports this functionality only for TextComponent/JTextComponent descendants. + // For our editor component we need this workaround. + myNeedToSelectPreviousChar = false; + getCaretModel().runForEachCaret(new CaretAction() { + @Override + public void perform(Caret caret) { + int caretOffset = caret.getOffset(); + if (caretOffset > 0) { + caret.setSelection(caretOffset - 1, caretOffset); + } + } + }); + } + int commitCount = e.getCommittedCharacterCount(); AttributedCharacterIterator text = e.getText(); diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 1613d3e292e3..114892b0266e 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -159,6 +159,8 @@ ide.mac.boldEditorTabs=false ide.mac.disableMacScrollbars=false ide.mac.disableMacScrollbars.restartRequired=true ide.mac.disableMacScrollbars.description=Disables OS X overlay scrollbars +ide.mac.pressAndHold.workaround=true +ide.mac.pressAndHold.workaround.description=Enable workaround for press-and-hold input method for accented characters on Mac OS ide.perProjectModality=false ide.perProjectModality.description=New modality approach. All dialogs are DOCUMENT_MODAL expect ide-wide dialogs From 9b6c46ede0b6f6dc62127d8e577a0c200d2da390 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 24 Feb 2015 18:45:42 +0300 Subject: [PATCH 230/231] github: we need write access to change issue state --- .../jetbrains/plugins/github/api/GithubApiUtil.java | 11 +++++------ .../plugins/github/tasks/GithubRepositoryEditor.java | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java index ad1812886cc0..dd51519db9f5 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java @@ -217,15 +217,14 @@ public class GithubApiUtil { } @NotNull - public static String getReadOnlyToken(@NotNull GithubConnection connection, - @NotNull String user, - @NotNull String repo, - @NotNull String note) + public static String getTasksToken(@NotNull GithubConnection connection, + @NotNull String user, + @NotNull String repo, + @NotNull String note) throws IOException { GithubRepo repository = getDetailedRepoInfo(connection, user, repo); - // TODO: use read-only token for private repos when it will be available - List scopes = repository.isPrivate() ? Collections.singletonList("repo") : Collections.emptyList(); + List scopes = repository.isPrivate() ? Collections.singletonList("repo") : Collections.singletonList("public_repo"); return getScopedToken(connection, scopes, note); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java index ba863621c969..e3e8daabb56a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java @@ -130,7 +130,7 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor Date: Tue, 24 Feb 2015 18:49:17 +0300 Subject: [PATCH 231/231] github: set default protocol --- .../org/jetbrains/plugins/github/tasks/GithubRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java index a8445b7f76ac..d59ac54e3a0b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java +++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepository.java @@ -55,7 +55,7 @@ public class GithubRepository extends BaseRepositoryImpl { public GithubRepository(GithubRepositoryType type) { super(type); - setUrl(GithubApiUtil.DEFAULT_GITHUB_HOST); + setUrl("https://" + GithubApiUtil.DEFAULT_GITHUB_HOST); } @NotNull