mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote branch 'origin/master'
This commit is contained in:
Generated
+14
-7
@@ -5,14 +5,21 @@
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-1.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-cglib-1.0.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/easymockclassextension.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.3.0-RC2.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.3.0-RC2.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/objenesis-1.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/mockobjects-core-0.09.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/hamcrest-library-1.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/hamcrest-api-1.0.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/mockobjects-core-0.09.jar!/ " />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/hamcrest-core-1.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/hamcrest-library-1.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
<JAVADOC/>
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/hamcrest-core-1.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/hamcrest-library-1.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-2.5.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-junit4-2.5.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/dev/jmock-legacy-2.5.1.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -695,13 +695,13 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
|
||||
@Override
|
||||
public void sessionTerminated() {
|
||||
String statusMessage = "Auto make completed";
|
||||
String statusMessage = null/*"Auto make completed"*/;
|
||||
switch (myBuildStatus) {
|
||||
case SUCCESS:
|
||||
statusMessage = "Auto make completed successfully";
|
||||
//statusMessage = "Auto make completed successfully";
|
||||
break;
|
||||
case UP_TO_DATE:
|
||||
statusMessage = "All files are up-to-date";
|
||||
//statusMessage = "All files are up-to-date";
|
||||
break;
|
||||
case ERRORS:
|
||||
statusMessage = "Auto make completed with errors";
|
||||
@@ -710,9 +710,11 @@ public class CompileServerManager implements ApplicationComponent{
|
||||
statusMessage = "Auto make has been canceled";
|
||||
break;
|
||||
}
|
||||
final Notification notification = CompilerManager.NOTIFICATION_GROUP.createNotification(statusMessage, MessageType.INFO);
|
||||
if (!myProject.isDisposed()) {
|
||||
notification.notify(myProject);
|
||||
if (statusMessage != null) {
|
||||
final Notification notification = CompilerManager.NOTIFICATION_GROUP.createNotification(statusMessage, MessageType.INFO);
|
||||
if (!myProject.isDisposed()) {
|
||||
notification.notify(myProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,22 +73,20 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread<DebuggerComma
|
||||
}
|
||||
}
|
||||
|
||||
public void pushBack(DebuggerCommandImpl managerCommand) {
|
||||
if(myEvents.isClosed()) {
|
||||
public boolean pushBack(DebuggerCommandImpl managerCommand) {
|
||||
final boolean pushed = super.pushBack(managerCommand);
|
||||
if (!pushed) {
|
||||
managerCommand.notifyCancelled();
|
||||
}
|
||||
else {
|
||||
super.pushBack(managerCommand);
|
||||
}
|
||||
return pushed;
|
||||
}
|
||||
|
||||
public void schedule(DebuggerCommandImpl managerCommand) {
|
||||
if(myEvents.isClosed()) {
|
||||
public boolean schedule(DebuggerCommandImpl managerCommand) {
|
||||
final boolean scheduled = super.schedule(managerCommand);
|
||||
if (!scheduled) {
|
||||
managerCommand.notifyCancelled();
|
||||
}
|
||||
else {
|
||||
super.schedule(managerCommand);
|
||||
}
|
||||
return scheduled;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,36 +45,42 @@ public class EventQueue<E> {
|
||||
}
|
||||
}
|
||||
|
||||
public void pushBack(@NotNull E event, int priority) {
|
||||
public boolean pushBack(@NotNull E event, int priority) {
|
||||
if(LOG.isDebugEnabled()) {
|
||||
LOG.debug("pushBack event " + event);
|
||||
}
|
||||
|
||||
myLock.lock();
|
||||
try {
|
||||
assertOpen();
|
||||
if (isClosed()) {
|
||||
return false;
|
||||
}
|
||||
getEventsList(priority).addFirst(event);
|
||||
myEventsAvailable.signalAll();
|
||||
}
|
||||
finally {
|
||||
myLock.unlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void put(@NotNull E event, int priority) {
|
||||
public boolean put(@NotNull E event, int priority) {
|
||||
if(LOG.isDebugEnabled()) {
|
||||
LOG.debug("put event " + event);
|
||||
}
|
||||
|
||||
myLock.lock();
|
||||
try {
|
||||
assertOpen();
|
||||
if (isClosed()) {
|
||||
return false;
|
||||
}
|
||||
getEventsList(priority).offer(event);
|
||||
myEventsAvailable.signalAll();
|
||||
}
|
||||
finally {
|
||||
myLock.unlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private LinkedList<E> getEventsList(final int priority) {
|
||||
@@ -84,7 +90,6 @@ public class EventQueue<E> {
|
||||
public void close(){
|
||||
myLock.lock();
|
||||
try {
|
||||
assertOpen();
|
||||
myIsClosed = true;
|
||||
myEventsAvailable.signalAll();
|
||||
}
|
||||
@@ -93,10 +98,6 @@ public class EventQueue<E> {
|
||||
}
|
||||
}
|
||||
|
||||
private void assertOpen() {
|
||||
if (myIsClosed) throw new AssertionError("Already closed");
|
||||
}
|
||||
|
||||
private E getEvent() throws EventQueueClosedException {
|
||||
myLock.lock();
|
||||
try {
|
||||
|
||||
@@ -19,4 +19,8 @@ package com.intellij.debugger.impl;
|
||||
* @author lex
|
||||
*/
|
||||
public class EventQueueClosedException extends Exception {
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ public abstract class InvokeAndWaitThread<E extends DebuggerTask> extends Invoke
|
||||
* !!! Do not remove this code !!!
|
||||
* Otherwise it will be impossible to override schedule method
|
||||
*/
|
||||
public void schedule(E e) {
|
||||
super.schedule(e);
|
||||
public boolean schedule(E e) {
|
||||
return super.schedule(e);
|
||||
}
|
||||
|
||||
public void pushBack(E e) {
|
||||
super.pushBack(e);
|
||||
public boolean pushBack(E e) {
|
||||
return super.pushBack(e);
|
||||
}
|
||||
|
||||
public void invokeAndWait(final E runnable) {
|
||||
|
||||
@@ -172,18 +172,18 @@ public abstract class InvokeThread<E extends PrioritizedTask> {
|
||||
return request != null? request.getOwner() : null;
|
||||
}
|
||||
|
||||
public void schedule(E r) {
|
||||
public boolean schedule(E r) {
|
||||
if(LOG.isDebugEnabled()) {
|
||||
LOG.debug("schedule " + r + " in " + this);
|
||||
}
|
||||
myEvents.put(r, r.getPriority().ordinal());
|
||||
return myEvents.put(r, r.getPriority().ordinal());
|
||||
}
|
||||
|
||||
public void pushBack(E r) {
|
||||
public boolean pushBack(E r) {
|
||||
if(LOG.isDebugEnabled()) {
|
||||
LOG.debug("pushBack " + r + " in " + this);
|
||||
}
|
||||
myEvents.pushBack(r, r.getPriority().ordinal());
|
||||
return myEvents.pushBack(r, r.getPriority().ordinal());
|
||||
}
|
||||
|
||||
protected void switchToRequest(WorkerThreadRequest newWorkerThread) {
|
||||
|
||||
+3
-9
@@ -24,6 +24,7 @@ import com.intellij.execution.junit.RefactoringListeners;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
@@ -31,7 +32,6 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.SettingsEditor;
|
||||
import com.intellij.openapi.options.SettingsEditorGroup;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.DefaultJDOMExternalizer;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
@@ -138,19 +138,13 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration<JavaRunCo
|
||||
}
|
||||
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
if (ALTERNATIVE_JRE_PATH_ENABLED){
|
||||
if (ALTERNATIVE_JRE_PATH == null ||
|
||||
ALTERNATIVE_JRE_PATH.length() == 0 ||
|
||||
!JavaSdkImpl.checkForJre(ALTERNATIVE_JRE_PATH)){
|
||||
throw new RuntimeConfigurationWarning(ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.mesage", ALTERNATIVE_JRE_PATH));
|
||||
}
|
||||
}
|
||||
JavaParametersUtil.checkAlternativeJRE(this);
|
||||
final JavaRunConfigurationModule configurationModule = getConfigurationModule();
|
||||
final PsiClass psiClass = configurationModule.checkModuleAndClassName(MAIN_CLASS_NAME, ExecutionBundle.message("no.main.class.specified.error.text"));
|
||||
if (!PsiMethodUtil.hasMainMethod(psiClass)) {
|
||||
throw new RuntimeConfigurationWarning(ExecutionBundle.message("main.method.not.found.in.class.error.message", MAIN_CLASS_NAME));
|
||||
}
|
||||
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(this, getProject(), configurationModule.getModule());
|
||||
JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,11 @@ package com.intellij.execution.util;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.CommonJavaRunConfigurationParameters;
|
||||
import com.intellij.execution.ExecutionBundle;
|
||||
import com.intellij.execution.JavaExecutionUtil;
|
||||
import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.execution.configurations.RunConfigurationModule;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationWarning;
|
||||
import com.intellij.execution.configurations.SimpleJavaParameters;
|
||||
import com.intellij.execution.junit.JUnitUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -122,4 +124,15 @@ public class JavaParametersUtil {
|
||||
if (jdk == null) throw CantRunException.noJdkConfigured();
|
||||
return jdk;
|
||||
}
|
||||
|
||||
public static void checkAlternativeJRE(CommonJavaRunConfigurationParameters configuration) throws RuntimeConfigurationWarning {
|
||||
if (configuration.isAlternativeJrePathEnabled()) {
|
||||
if (configuration.getAlternativeJrePath() == null ||
|
||||
configuration.getAlternativeJrePath().length() == 0 ||
|
||||
!JavaSdk.checkForJre(configuration.getAlternativeJrePath())) {
|
||||
throw new RuntimeConfigurationWarning(
|
||||
ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.mesage", configuration.getAlternativeJrePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,12 @@ public class ProjectJdksEditor extends DialogWrapper {
|
||||
|
||||
|
||||
public ProjectJdksEditor(final Sdk jdk, Project project, Component parent) {
|
||||
this(jdk, parent, new ProjectJdksConfigurable(project));
|
||||
}
|
||||
|
||||
public ProjectJdksEditor(final Sdk jdk, Component parent, ProjectJdksConfigurable configurable) {
|
||||
super(parent, true);
|
||||
myConfigurable = new ProjectJdksConfigurable(project);
|
||||
myConfigurable = configurable;
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
public void run() {
|
||||
myConfigurable.selectNodeInTree(jdk != null ? jdk.getName() : null);
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.intellij.openapi.roots.ui.configuration;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.util.projectWizard.ProjectJdkListRenderer;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
@@ -47,8 +46,7 @@ import java.util.Comparator;
|
||||
* @author Eugene Zhuravlev
|
||||
* @since May 18, 2005
|
||||
*/
|
||||
class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
private final JButton myEditButton = new JButton(ApplicationBundle.message("button.edit"));
|
||||
public class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
|
||||
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel) {
|
||||
super(new JdkComboBoxModel(jdkModel));
|
||||
@@ -101,17 +99,22 @@ class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
return minSize;
|
||||
}
|
||||
|
||||
public JButton createSetupButton(final Project project, final ProjectSdksModel jdksModel, final JdkComboBoxItem firstItem) {
|
||||
return createSetupButton(project, jdksModel, firstItem, null, false);
|
||||
public void setSetupButton(final JButton setUpButton,
|
||||
final Project project,
|
||||
final ProjectSdksModel jdksModel,
|
||||
final JdkComboBoxItem firstItem,
|
||||
@Nullable final Condition<Sdk> additionalSetup,
|
||||
final boolean moduleJdkSetup) {
|
||||
setSetupButton(setUpButton, project, jdksModel, firstItem, additionalSetup,
|
||||
ProjectBundle.message("project.roots.set.up.jdk.title", moduleJdkSetup ? 1 : 2));
|
||||
}
|
||||
|
||||
|
||||
public JButton createSetupButton(final Project project,
|
||||
final ProjectSdksModel jdksModel,
|
||||
final JdkComboBoxItem firstItem,
|
||||
@Nullable final Condition<Sdk> additionalSetup,
|
||||
final boolean moduleJdkSetup) {
|
||||
final JButton setUpButton = new JButton(ApplicationBundle.message("button.new"));
|
||||
public void setSetupButton(final JButton setUpButton,
|
||||
final Project project,
|
||||
final ProjectSdksModel jdksModel,
|
||||
final JdkComboBoxItem firstItem,
|
||||
@Nullable final Condition<Sdk> additionalSetup,
|
||||
final String actionGroupTitle) {
|
||||
setUpButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final JdkListConfigurable configurable = JdkListConfigurable.getInstance(project);
|
||||
@@ -129,16 +132,16 @@ class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
}
|
||||
});
|
||||
JBPopupFactory.getInstance()
|
||||
.createActionGroupPopup(ProjectBundle.message("project.roots.set.up.jdk.title", moduleJdkSetup ? 1 : 2), group,
|
||||
DataManager.getInstance().getDataContext(JdkComboBox.this), JBPopupFactory.ActionSelectionAid.MNEMONICS, false)
|
||||
.createActionGroupPopup(actionGroupTitle, group,
|
||||
DataManager.getInstance().getDataContext(JdkComboBox.this), JBPopupFactory.ActionSelectionAid.MNEMONICS,
|
||||
false)
|
||||
.showUnderneathOf(setUpButton);
|
||||
}
|
||||
});
|
||||
return setUpButton;
|
||||
}
|
||||
|
||||
public void appendEditButton(final Project project, final JPanel panel, GridBagConstraints gc, final Computable<Sdk> retrieveJDK){
|
||||
myEditButton.addActionListener(new ActionListener() {
|
||||
public void setEditButton(final JButton editButton, final Project project, final Computable<Sdk> retrieveJDK){
|
||||
editButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final Sdk projectJdk = retrieveJDK.compute();
|
||||
if (projectJdk != null) {
|
||||
@@ -146,17 +149,17 @@ class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
}
|
||||
}
|
||||
});
|
||||
addActionListener(new ActionListener(){
|
||||
addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final JdkComboBoxItem selectedItem = getSelectedItem();
|
||||
if (selectedItem instanceof ProjectJdkComboBoxItem) {
|
||||
myEditButton.setEnabled(ProjectStructureConfigurable.getInstance(project).getProjectJdksModel().getProjectSdk() != null);
|
||||
} else {
|
||||
myEditButton.setEnabled(!(selectedItem instanceof InvalidJdkComboBoxItem) && selectedItem != null && selectedItem.getJdk() != null);
|
||||
editButton.setEnabled(ProjectStructureConfigurable.getInstance(project).getProjectJdksModel().getProjectSdk() != null);
|
||||
}
|
||||
else {
|
||||
editButton.setEnabled(!(selectedItem instanceof InvalidJdkComboBoxItem) && selectedItem != null && selectedItem.getJdk() != null);
|
||||
}
|
||||
}
|
||||
});
|
||||
panel.add(myEditButton, gc);
|
||||
}
|
||||
|
||||
public JdkComboBoxItem getSelectedItem() {
|
||||
@@ -260,6 +263,11 @@ class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
return myJdk;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSdkName() {
|
||||
return myJdk != null ? myJdk.getName() : null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return myJdk.getName();
|
||||
}
|
||||
@@ -286,15 +294,19 @@ class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
}
|
||||
|
||||
private static class InvalidJdkComboBoxItem extends JdkComboBoxItem {
|
||||
private final String myName;
|
||||
private final String mySdkName;
|
||||
|
||||
public InvalidJdkComboBoxItem(String name) {
|
||||
super(null);
|
||||
myName = ProjectBundle.message("jdk.combo.box.invalid.item", name);
|
||||
mySdkName = name;
|
||||
}
|
||||
|
||||
public String getSdkName() {
|
||||
return mySdkName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return myName;
|
||||
return ProjectBundle.message("jdk.combo.box.invalid.item", mySdkName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -17,6 +17,7 @@
|
||||
package com.intellij.openapi.roots.ui.configuration;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
@@ -119,17 +120,18 @@ public abstract class ModuleJdkConfigurable implements Disposable {
|
||||
GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
|
||||
new Insets(6, 6, 12, 0), 0, 0));
|
||||
final Project project = getRootModel().getModule().getProject();
|
||||
final JButton setUpButton = myCbModuleJdk
|
||||
.createSetupButton(project, myJdksModel, new JdkComboBox.ProjectJdkComboBoxItem(), new Condition<Sdk>(){
|
||||
final JButton setUpButton = new JButton(ApplicationBundle.message("button.new"));
|
||||
myCbModuleJdk
|
||||
.setSetupButton(setUpButton, project, myJdksModel, new JdkComboBox.ProjectJdkComboBoxItem(), new Condition<Sdk>() {
|
||||
public boolean value(Sdk jdk) {
|
||||
final Sdk projectJdk = myJdksModel.getProjectSdk();
|
||||
if (projectJdk == null){
|
||||
if (projectJdk == null) {
|
||||
final int res =
|
||||
Messages.showYesNoDialog(myJdkPanel,
|
||||
ProjectBundle.message("project.roots.no.jdk.on.project.message"),
|
||||
ProjectBundle.message("project.roots.no.jdk.on.projecct.title"),
|
||||
ProjectBundle.message("project.roots.no.jdk.on.project.title"),
|
||||
Messages.getInformationIcon());
|
||||
if (res == DialogWrapper.OK_EXIT_CODE){
|
||||
if (res == DialogWrapper.OK_EXIT_CODE) {
|
||||
myJdksModel.setProjectSdk(jdk);
|
||||
return true;
|
||||
}
|
||||
@@ -140,12 +142,16 @@ public abstract class ModuleJdkConfigurable implements Disposable {
|
||||
myJdkPanel.add(setUpButton, new GridBagConstraints(2, 0, 1, 1, 0, 0,
|
||||
GridBagConstraints.WEST, GridBagConstraints.NONE,
|
||||
new Insets(0, 4, 7, 0), 0, 0));
|
||||
myCbModuleJdk.appendEditButton(getRootModel().getModule().getProject(), myJdkPanel, new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 1.0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 4, 7, 0), 0, 0) , new Computable<Sdk>() {
|
||||
final JButton editButton = new JButton(ApplicationBundle.message("button.edit"));
|
||||
myCbModuleJdk.setEditButton(editButton, getRootModel().getModule().getProject(), new Computable<Sdk>() {
|
||||
@Nullable
|
||||
public Sdk compute() {
|
||||
return getRootModel().getSdk();
|
||||
}
|
||||
});
|
||||
myJdkPanel.add(editButton,
|
||||
new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 1.0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE,
|
||||
new Insets(0, 4, 7, 0), 0, 0));
|
||||
}
|
||||
|
||||
private void clearCaches() {
|
||||
|
||||
+8
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.openapi.roots.ui.configuration;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationBundle;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -90,14 +91,19 @@ public class ProjectJdkConfigurable implements UnnamedConfigurable {
|
||||
});
|
||||
myJdkPanel.add(new JLabel(ProjectBundle.message("module.libraries.target.jdk.project.radio")), new GridBagConstraints(0, 0, 3, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 4, 0), 0, 0));
|
||||
myJdkPanel.add(myCbProjectJdk, new GridBagConstraints(0, 1, 1, 1, 0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 4, 0, 0), 0, 0));
|
||||
final JButton setUpButton = myCbProjectJdk.createSetupButton(myProject, myJdksModel, new JdkComboBox.NoneJdkComboBoxItem());
|
||||
final JButton setUpButton = new JButton(ApplicationBundle.message("button.new"));
|
||||
myCbProjectJdk.setSetupButton(setUpButton, myProject, myJdksModel, new JdkComboBox.NoneJdkComboBoxItem(), null, false);
|
||||
myJdkPanel.add(setUpButton, new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 4, 0, 0), 0, 0));
|
||||
myCbProjectJdk.appendEditButton(myProject, myJdkPanel, new GridBagConstraints(GridBagConstraints.RELATIVE, 1, 1, 1, 1.0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 4, 0, 0), 0, 0), new Computable<Sdk>() {
|
||||
final JButton editButton = new JButton(ApplicationBundle.message("button.edit"));
|
||||
myCbProjectJdk.setEditButton(editButton, myProject, new Computable<Sdk>() {
|
||||
@Nullable
|
||||
public Sdk compute() {
|
||||
return myJdksModel.getProjectSdk();
|
||||
}
|
||||
});
|
||||
|
||||
myJdkPanel.add(editButton, new GridBagConstraints(GridBagConstraints.RELATIVE, 1, 1, 1, 1.0, 0, GridBagConstraints.NORTHWEST,
|
||||
GridBagConstraints.NONE, new Insets(0, 4, 0, 0), 0, 0));
|
||||
}
|
||||
return myJdkPanel;
|
||||
}
|
||||
|
||||
+6
-3
@@ -57,13 +57,16 @@ public class ProjectJdksConfigurable extends MasterDetailsComponent {
|
||||
|
||||
private final ProjectSdksModel myProjectJdksModel;
|
||||
private final Project myProject;
|
||||
@NonNls
|
||||
@NonNls
|
||||
private static final String SPLITTER_PROPORTION = "project.jdk.splitter";
|
||||
|
||||
public ProjectJdksConfigurable(Project project) {
|
||||
super();
|
||||
this(project, ProjectStructureConfigurable.getInstance(project).getProjectJdksModel());
|
||||
}
|
||||
|
||||
public ProjectJdksConfigurable(Project project, ProjectSdksModel sdksModel) {
|
||||
myProject = project;
|
||||
myProjectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
|
||||
myProjectJdksModel = sdksModel;
|
||||
initTree();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
|
||||
&& (JspPsiUtil.isInJspFile(psiFile) ?
|
||||
CodeInsightSettings.getInstance().JSP_ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY :
|
||||
CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY)
|
||||
&& codeAnalyzer.canChangeFileSilently(psiFile)
|
||||
&& (ApplicationManager.getApplication().isUnitTestMode() || codeAnalyzer.canChangeFileSilently(psiFile))
|
||||
&& !autoImportWillInsertUnexpectedCharacters(classes[0])
|
||||
) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
|
||||
+2
-1
@@ -43,6 +43,7 @@ import java.util.List;
|
||||
*/
|
||||
public class JavaAnonymousClassesNodeProvider implements FileStructureNodeProvider<JavaAnonymousClassTreeElement>, PropertyOwner {
|
||||
public static final String ID = "SHOW_ANONYMOUS";
|
||||
public static final String JAVA_ANONYMOUS_PROPERTY_NAME = "java.anonymous.provider";
|
||||
|
||||
@Override
|
||||
public Collection<JavaAnonymousClassTreeElement> provideNodes(TreeElement node) {
|
||||
@@ -87,6 +88,6 @@ public class JavaAnonymousClassesNodeProvider implements FileStructureNodeProvid
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPropertyName() {
|
||||
return "java.anonymous.provider";
|
||||
return JAVA_ANONYMOUS_PROPERTY_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ public class JavaCodeBlockModificationListener implements PsiTreeChangePreproces
|
||||
private void processChange(final PsiElement parent, final PsiElement child1, final PsiElement child2) {
|
||||
try {
|
||||
if (!isInsideCodeBlock(parent)) {
|
||||
if (parent != null && isClassOwner(parent.getContainingFile()) || isClassOwner(child1) || isClassOwner(child2) || isSourceDir(parent)) {
|
||||
if (parent != null && isClassOwner(parent.getContainingFile()) ||
|
||||
isClassOwner(child1) || isClassOwner(child2) || isSourceDir(parent) ||
|
||||
(parent != null && isClassOwner(parent.getParent()))) {
|
||||
myModificationTracker.incCounter();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -17,7 +17,10 @@ package com.intellij.refactoring.memberPullUp;
|
||||
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.statistics.StatisticsInfo;
|
||||
import com.intellij.psi.statistics.StatisticsManager;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
@@ -57,6 +60,7 @@ public class PullUpDialog extends RefactoringDialog {
|
||||
private List<MemberInfo> myMemberInfos;
|
||||
private DocCommentPanel myJavaDocPanel;
|
||||
private JComboBox myClassCombo;
|
||||
private static final String PULL_UP_STATISTICS_KEY = "pull.up##";
|
||||
|
||||
public interface Callback {
|
||||
boolean checkConflicts(PullUpDialog dialog);
|
||||
@@ -127,11 +131,10 @@ public class PullUpDialog extends RefactoringDialog {
|
||||
myClassCombo.setRenderer(new ClassCellRenderer(myClassCombo.getRenderer()));
|
||||
classComboLabel.setText(RefactoringBundle.message("pull.up.members.to", UsageViewUtil.getLongName(myClass)));
|
||||
classComboLabel.setLabelFor(myClassCombo);
|
||||
|
||||
PsiClass nearestBase = RefactoringHierarchyUtil.getNearestBaseClass(myClass, false);
|
||||
final PsiClass preselection = getPreselection();
|
||||
int indexToSelect = 0;
|
||||
if (nearestBase != null) {
|
||||
indexToSelect = mySuperClasses.indexOf(nearestBase);
|
||||
if (preselection != null) {
|
||||
indexToSelect = mySuperClasses.indexOf(preselection);
|
||||
}
|
||||
myClassCombo.setSelectedIndex(indexToSelect);
|
||||
myClassCombo.addItemListener(new ItemListener() {
|
||||
@@ -152,6 +155,27 @@ public class PullUpDialog extends RefactoringDialog {
|
||||
return panel;
|
||||
}
|
||||
|
||||
private PsiClass getPreselection() {
|
||||
PsiClass preselection = RefactoringHierarchyUtil.getNearestBaseClass(myClass, false);
|
||||
|
||||
final String statKey = PULL_UP_STATISTICS_KEY + myClass.getQualifiedName();
|
||||
for (StatisticsInfo info : StatisticsManager.getInstance().getAllValues(statKey)) {
|
||||
final String superClassName = info.getValue();
|
||||
PsiClass superClass = null;
|
||||
for (PsiClass aClass : mySuperClasses) {
|
||||
if (Comparing.strEqual(superClassName, aClass.getQualifiedName())) {
|
||||
superClass = aClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (superClass != null && StatisticsManager.getInstance().getUseCount(info) > 0) {
|
||||
preselection = superClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return preselection;
|
||||
}
|
||||
|
||||
protected void doHelpAction() {
|
||||
HelpManager.getInstance().invokeHelp(HelpID.MEMBERS_PULL_UP);
|
||||
}
|
||||
@@ -168,7 +192,9 @@ public class PullUpDialog extends RefactoringDialog {
|
||||
protected void doAction() {
|
||||
if (!myCallback.checkConflicts(this)) return;
|
||||
JavaRefactoringSettings.getInstance().PULL_UP_MEMBERS_JAVADOC = myJavaDocPanel.getPolicy();
|
||||
|
||||
StatisticsManager
|
||||
.getInstance().incUseCount(new StatisticsInfo(PULL_UP_STATISTICS_KEY + myClass.getQualifiedName(), getSuperClass().getQualifiedName()));
|
||||
|
||||
invokeRefactoring(new PullUpHelper(myClass, getSuperClass(), getSelectedMemberInfos(),
|
||||
new DocCommentPolicy(getJavaDocPolicy())));
|
||||
close(OK_EXIT_CODE);
|
||||
|
||||
@@ -21,10 +21,12 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
|
||||
import com.intellij.psi.scope.util.PsiScopesUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ResolveClassUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.ResolveClassUtil");
|
||||
|
||||
@Nullable
|
||||
public static PsiClass resolveClass(PsiJavaCodeReferenceElement ref) {
|
||||
if (ref instanceof PsiJavaCodeReferenceElementImpl && ((PsiJavaCodeReferenceElementImpl)ref).getKind() == PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND){
|
||||
PsiElement parent = ref.getParent();
|
||||
|
||||
@@ -138,7 +138,7 @@ public class PsiScopesUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean resolveAndWalk(PsiScopeProcessor processor, PsiJavaCodeReferenceElement ref, PsiElement maxScope) {
|
||||
public static boolean resolveAndWalk(PsiScopeProcessor processor, PsiJavaCodeReferenceElement ref, @Nullable PsiElement maxScope) {
|
||||
return resolveAndWalk(processor, ref, maxScope, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Constructor {
|
||||
int num1;
|
||||
int num2;
|
||||
|
||||
Constructor() {<caret>}
|
||||
void foo() {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
-Constructor.java
|
||||
-Constructor
|
||||
[Constructor()]
|
||||
foo():void
|
||||
num1:int
|
||||
num2:int
|
||||
@@ -0,0 +1,7 @@
|
||||
class Field {
|
||||
int num1;
|
||||
int <caret>num2;
|
||||
|
||||
Field() {}
|
||||
void foo() {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
-Field.java
|
||||
-Field
|
||||
Field()
|
||||
foo():void
|
||||
num1:int
|
||||
[num2:int]
|
||||
@@ -0,0 +1,7 @@
|
||||
class InsideClass {
|
||||
int num1;
|
||||
int num2;
|
||||
<caret>
|
||||
InsideClass() {}
|
||||
void foo() {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
-InsideClass.java
|
||||
-[InsideClass]
|
||||
InsideClass()
|
||||
foo():void
|
||||
num1:int
|
||||
num2:int
|
||||
@@ -0,0 +1,7 @@
|
||||
class Method {
|
||||
int num1;
|
||||
int num2;
|
||||
|
||||
Method() {}
|
||||
void foo() {<caret>}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
-Method.java
|
||||
-Method
|
||||
Method()
|
||||
[foo():void]
|
||||
num1:int
|
||||
num2:int
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.ide.fileStructure;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class JavaFileStructureSelectionTest extends JavaFileStructureTestCase {
|
||||
@Override
|
||||
protected String getTestDataFolderName() {
|
||||
return "selection";
|
||||
}
|
||||
|
||||
public void testField() throws Exception {checkTree();}
|
||||
public void testMethod() throws Exception {checkTree();}
|
||||
public void testConstructor() throws Exception {checkTree();}
|
||||
public void testInsideClass() throws Exception {checkTree();}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.ide.fileStructure;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.ide.structureView.impl.java.JavaAnonymousClassesNodeProvider;
|
||||
import com.intellij.ide.util.FileStructurePopup;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.testFramework.FileStructureTestBase;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public abstract class JavaFileStructureTestCase extends FileStructureTestBase {
|
||||
private boolean myShowAnonymousByDefault;
|
||||
|
||||
protected abstract String getTestDataFolderName();
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myShowAnonymousByDefault = PropertiesComponent.getInstance().getBoolean(getAnonymousPropertyName(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFileExtension() {
|
||||
return "java";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
PropertiesComponent.getInstance().setValue(getAnonymousPropertyName(), Boolean.toString(myShowAnonymousByDefault));
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private static String getAnonymousPropertyName() {
|
||||
return FileStructurePopup.getPropertyName(JavaAnonymousClassesNodeProvider.JAVA_ANONYMOUS_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() + "/fileStructure/" + getTestDataFolderName();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -17,6 +17,7 @@ package com.intellij.execution.util;
|
||||
|
||||
import com.intellij.execution.CommonProgramRunConfigurationParameters;
|
||||
import com.intellij.execution.configurations.ModuleBasedConfiguration;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationWarning;
|
||||
import com.intellij.execution.configurations.SimpleProgramParameters;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -26,6 +27,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -36,6 +38,19 @@ public class ProgramParametersUtil {
|
||||
|
||||
parameters.getProgramParametersList().addParametersString(configuration.getProgramParameters());
|
||||
|
||||
parameters.setWorkingDirectory(getWorkingDir(configuration, project, module));
|
||||
|
||||
parameters.setupEnvs(configuration.getEnvs(), configuration.isPassParentEnvs());
|
||||
if (parameters.getEnv() != null) {
|
||||
Map<String, String> expanded = new HashMap<String, String>();
|
||||
for (Map.Entry<String, String> each : parameters.getEnv().entrySet()) {
|
||||
expanded.put(each.getKey(), expandPath(each.getValue(), module, project));
|
||||
}
|
||||
parameters.setEnv(expanded);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getWorkingDir(CommonProgramRunConfigurationParameters configuration, Project project, Module module) {
|
||||
String workingDirectory = configuration.getWorkingDirectory();
|
||||
VirtualFile baseDir = project.getBaseDir();
|
||||
|
||||
@@ -46,15 +61,14 @@ public class ProgramParametersUtil {
|
||||
if (!FileUtil.isAbsolute(workingDirectory) && baseDir != null) {
|
||||
workingDirectory = baseDir.getPath() + "/" + workingDirectory;
|
||||
}
|
||||
parameters.setWorkingDirectory(workingDirectory);
|
||||
return workingDirectory;
|
||||
}
|
||||
|
||||
parameters.setupEnvs(configuration.getEnvs(), configuration.isPassParentEnvs());
|
||||
if (parameters.getEnv() != null) {
|
||||
Map<String, String> expanded = new HashMap<String, String>();
|
||||
for (Map.Entry<String, String> each : parameters.getEnv().entrySet()) {
|
||||
expanded.put(each.getKey(), expandPath(each.getValue(), module, project));
|
||||
}
|
||||
parameters.setEnv(expanded);
|
||||
public static void checkWorkingDirectoryExist(CommonProgramRunConfigurationParameters configuration, Project project, Module module)
|
||||
throws RuntimeConfigurationWarning {
|
||||
final String workingDir = getWorkingDir(configuration, project, module);
|
||||
if (!new File(workingDir).exists()) {
|
||||
throw new RuntimeConfigurationWarning("Working directory '" + workingDir + "' doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public class ViewStructureAction extends AnAction {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FileStructurePopup createPopup(final Editor editor, Project project, Navigatable navigatable, final FileEditor fileEditor) {
|
||||
public static FileStructurePopup createPopup(final Editor editor, Project project, @Nullable Navigatable navigatable, final FileEditor fileEditor) {
|
||||
final StructureViewBuilder structureViewBuilder = fileEditor.getStructureViewBuilder();
|
||||
if (structureViewBuilder == null) return null;
|
||||
StructureView structureView = structureViewBuilder.createStructureView(fileEditor, project);
|
||||
|
||||
@@ -149,6 +149,7 @@ public class FileStructurePopup implements Disposable {
|
||||
myTree = new JBTreeWithHintProvider(new DefaultMutableTreeNode(myTreeStructure.getRootElement())) {
|
||||
@Override
|
||||
protected PsiElement getPsiElementForHint(Object selectedValue) {
|
||||
//noinspection ConstantConditions
|
||||
return getPsi((FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)selectedValue).getUserObject());
|
||||
}
|
||||
};
|
||||
@@ -218,12 +219,13 @@ public class FileStructurePopup implements Disposable {
|
||||
return current.isEmpty() ? null : findClosestTo(myInitialPsiElement, current);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object findClosestTo(PsiElement path, ArrayList<ObjectWithWeight> paths) {
|
||||
if (path == null || myInitialPsiElement == null) {
|
||||
return paths.get(0).node;
|
||||
}
|
||||
final Set<PsiElement> parents = getAllParents(myInitialPsiElement);
|
||||
Object cur = paths.get(0).node;
|
||||
ArrayList<TreePath> cur = new ArrayList<TreePath>();
|
||||
int max = -1;
|
||||
for (ObjectWithWeight p : paths) {
|
||||
final Object last = ((TreePath)p.node).getLastPathComponent();
|
||||
@@ -238,14 +240,21 @@ public class FileStructurePopup implements Disposable {
|
||||
final int size = ContainerUtil.intersection(parents, elements).size();
|
||||
if (size > max) {
|
||||
max = size;
|
||||
cur = p.node;
|
||||
} else if (size == max && size == parents.size()) {
|
||||
cur = p.node;
|
||||
cur.clear();
|
||||
cur.add((TreePath)p.node);
|
||||
} else if (size == max) {
|
||||
cur.add((TreePath)p.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cur;
|
||||
Collections.sort(cur, new Comparator<TreePath>() {
|
||||
@Override
|
||||
public int compare(TreePath o1, TreePath o2) {
|
||||
return o2.getPathCount() - o1.getPathCount();
|
||||
}
|
||||
});
|
||||
return cur.isEmpty() ? null : cur.get(0);
|
||||
}
|
||||
|
||||
class ObjectWithWeight {
|
||||
@@ -285,7 +294,7 @@ public class FileStructurePopup implements Disposable {
|
||||
mySpeedSearch.setComparator(new SpeedSearchComparator(false, true));
|
||||
|
||||
final FileStructurePopupFilter filter = new FileStructurePopupFilter();
|
||||
myFilteringStructure = new FilteringTreeStructure(filter, myTreeStructure, false);
|
||||
myFilteringStructure = new FilteringTreeStructure(filter, myTreeStructure, ApplicationManager.getApplication().isUnitTestMode());
|
||||
myAbstractTreeBuilder = new FilteringTreeBuilder(myTree, filter, myFilteringStructure, null) {
|
||||
@Override
|
||||
protected boolean validateNode(Object child) {
|
||||
@@ -385,35 +394,38 @@ public class FileStructurePopup implements Disposable {
|
||||
});
|
||||
}
|
||||
});
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myPopup);
|
||||
alarm.addRequest(new Runnable() {
|
||||
String filter = "";
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, myPopup);
|
||||
alarm.addRequest(new Runnable() {
|
||||
String filter = "";
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
alarm.cancelAllRequests();
|
||||
String prefix = mySpeedSearch.getEnteredPrefix();
|
||||
myTree.getEmptyText().setText(StringUtil.isEmpty(prefix) ? "Nothing to show" : "Can't find '" + prefix + "'");
|
||||
if (prefix == null) prefix = "";
|
||||
@Override
|
||||
public void run() {
|
||||
alarm.cancelAllRequests();
|
||||
String prefix = mySpeedSearch.getEnteredPrefix();
|
||||
myTree.getEmptyText().setText(StringUtil.isEmpty(prefix) ? "Nothing to show" : "Can't find '" + prefix + "'");
|
||||
if (prefix == null) prefix = "";
|
||||
|
||||
if (!filter.equals(prefix)) {
|
||||
filter = prefix;
|
||||
myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myTree.repaint();
|
||||
//if (mySpeedSearch.isPopupActive()) {
|
||||
// mySpeedSearch.refreshSelection();
|
||||
//}
|
||||
}
|
||||
});
|
||||
if (!filter.equals(prefix)) {
|
||||
filter = prefix;
|
||||
myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myTree.repaint();
|
||||
//if (mySpeedSearch.isPopupActive()) {
|
||||
// mySpeedSearch.refreshSelection();
|
||||
//}
|
||||
}
|
||||
});
|
||||
}
|
||||
alarm.addRequest(this, 300);
|
||||
}
|
||||
alarm.addRequest(this, 300);
|
||||
}
|
||||
}, 300);
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectPsiElement(PsiElement element) {
|
||||
@Nullable
|
||||
public FilteringTreeStructure.FilteringNode selectPsiElement(PsiElement element) {
|
||||
Set<PsiElement> parents = getAllParents(element);
|
||||
|
||||
FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)myAbstractTreeBuilder.getRootElement();
|
||||
@@ -432,11 +444,11 @@ public class FileStructurePopup implements Disposable {
|
||||
if (myAbstractTreeBuilder.getSelectedElements().isEmpty()) {
|
||||
TreeUtil.selectFirstNode(myTree);
|
||||
}
|
||||
return;
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
TreeUtil.selectFirstNode(myTree);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Set<PsiElement> getAllParents(PsiElement element) {
|
||||
@@ -478,7 +490,7 @@ public class FileStructurePopup implements Disposable {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiElement getCurrentElement(@Nullable final PsiFile psiFile) {
|
||||
public PsiElement getCurrentElement(@Nullable final PsiFile psiFile) {
|
||||
if (psiFile == null) return null;
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
@@ -710,7 +722,7 @@ public class FileStructurePopup implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPropertyName(String propertyName) {
|
||||
public static String getPropertyName(String propertyName) {
|
||||
return propertyName + ".file.structure.state";
|
||||
}
|
||||
|
||||
@@ -718,6 +730,18 @@ public class FileStructurePopup implements Disposable {
|
||||
myTitle = title;
|
||||
}
|
||||
|
||||
public Tree getTree() {
|
||||
return myTree;
|
||||
}
|
||||
|
||||
public TreeSpeedSearch getSpeedSearch() {
|
||||
return mySpeedSearch;
|
||||
}
|
||||
|
||||
public FilteringTreeBuilder getTreeBuilder() {
|
||||
return myAbstractTreeBuilder;
|
||||
}
|
||||
|
||||
private class FileStructurePopupFilter implements ElementFilter {
|
||||
private String myLastFilter = null;
|
||||
private HashSet<Object> myVisibleParents = new HashSet<Object>();
|
||||
|
||||
+23
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.openapi.roots.impl;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleJdkOrderEntry;
|
||||
@@ -29,6 +30,7 @@ import org.jdom.Attribute;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
@@ -62,8 +64,7 @@ public class ModuleJdkOrderEntryImpl extends LibraryOrderEntryBaseImpl implement
|
||||
|
||||
final String jdkName = jdkNameAttribute.getValue();
|
||||
final String jdkType = element.getAttributeValue(JDK_TYPE_ATTR);
|
||||
final ProjectJdkTable projectJdkTable = ProjectJdkTable.getInstance();
|
||||
final Sdk jdkByName = projectJdkTable.findJdk(jdkName, jdkType);
|
||||
final Sdk jdkByName = findJdk(jdkName, jdkType);
|
||||
if (jdkByName == null) {
|
||||
init(null, jdkName, jdkType);
|
||||
}
|
||||
@@ -72,6 +73,26 @@ public class ModuleJdkOrderEntryImpl extends LibraryOrderEntryBaseImpl implement
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class SdkFinder {
|
||||
private static final ExtensionPointName<SdkFinder> EP_NAME = ExtensionPointName.create("com.intellij.sdkFinder");
|
||||
|
||||
@Nullable
|
||||
public Sdk findSdk(String name, String sdkType) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Sdk findJdk(final String jdkName, final String jdkType) {
|
||||
for (SdkFinder sdkFinder : SdkFinder.EP_NAME.getExtensions()) {
|
||||
final Sdk sdk = sdkFinder.findSdk(jdkName, jdkType);
|
||||
if (sdk != null) {
|
||||
return sdk;
|
||||
}
|
||||
}
|
||||
final ProjectJdkTable projectJdkTable = ProjectJdkTable.getInstance();
|
||||
return projectJdkTable.findJdk(jdkName, jdkType);
|
||||
}
|
||||
|
||||
|
||||
private ModuleJdkOrderEntryImpl(ModuleJdkOrderEntryImpl that, RootModelImpl rootModel, ProjectRootManagerImpl projectRootManager) {
|
||||
|
||||
+2
@@ -132,6 +132,8 @@ public class InjectedLanguageUtil {
|
||||
if (file == null || !file.isPhysical() && file.getOriginalFile() == file) return;
|
||||
}
|
||||
|
||||
if (containingFile.getViewProvider() instanceof InjectedFileViewProvider) return; // no injection inside injection
|
||||
|
||||
PsiElement inTree = loadTree(host, containingFile);
|
||||
if (inTree != host) {
|
||||
host = inTree;
|
||||
|
||||
@@ -2362,7 +2362,7 @@ public class AbstractTreeUi {
|
||||
|
||||
final ActionCallback done = new ActionCallback();
|
||||
|
||||
invokeLaterIfNeeded(new Runnable() {
|
||||
final Runnable cancelUpdate = new Runnable() {
|
||||
public void run() {
|
||||
if (isReleased()) {
|
||||
done.setRejected();
|
||||
@@ -2371,21 +2371,29 @@ public class AbstractTreeUi {
|
||||
|
||||
if (myResettingToReadyNow.get()) {
|
||||
_getReady().notify(done);
|
||||
} else if (isReady()) {
|
||||
}
|
||||
else if (isReady()) {
|
||||
resetToReadyNow();
|
||||
done.setDone();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (isIdle() && hasPendingWork()) {
|
||||
resetToReadyNow();
|
||||
done.setDone();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
_getReady().notify(done);
|
||||
}
|
||||
}
|
||||
|
||||
maybeReady();
|
||||
}
|
||||
}, false);
|
||||
};
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
cancelUpdate.run();
|
||||
} else {
|
||||
invokeLaterIfNeeded(cancelUpdate, false);
|
||||
}
|
||||
|
||||
if (isEdt() || isPassthroughMode()) {
|
||||
maybeReady();
|
||||
@@ -3680,7 +3688,7 @@ public class AbstractTreeUi {
|
||||
}
|
||||
|
||||
public void userSelect(final Object[] elements, final Runnable onDone, final boolean addToSelection, boolean scroll) {
|
||||
_select(elements, onDone, addToSelection, true, false, scroll, false, true, true);
|
||||
_select(elements, onDone, addToSelection, true, false, scroll, false, true, !ApplicationManager.getApplication().isUnitTestMode());
|
||||
}
|
||||
|
||||
void _select(final Object[] elements,
|
||||
|
||||
+28
-11
@@ -18,6 +18,7 @@ package com.intellij.ui.treeStructure.filtered;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeStructure;
|
||||
import com.intellij.ide.util.treeView.NodeDescriptor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.speedSearch.ElementFilter;
|
||||
@@ -120,7 +121,7 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder {
|
||||
myRefilterQueue.cancelAllUpdates();
|
||||
}
|
||||
final ActionCallback callback = new ActionCallback();
|
||||
getUi().cancelUpdate().doWhenProcessed(new Runnable() {
|
||||
final Runnable afterCancelUpdate = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myRefilterQueue == null || now) {
|
||||
@@ -145,7 +146,12 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder {
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
getUi().cancelUpdate().doWhenProcessed(afterCancelUpdate);
|
||||
} else {
|
||||
afterCancelUpdate.run();
|
||||
}
|
||||
|
||||
return callback;
|
||||
}
|
||||
@@ -155,7 +161,7 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder {
|
||||
final ActionCallback selectionDone = new ActionCallback();
|
||||
|
||||
getFilteredStructure().refilter();
|
||||
queueUpdate().doWhenProcessed(new Runnable() {
|
||||
final Runnable selectionRunnable = new Runnable() {
|
||||
public void run() {
|
||||
revalidateTree();
|
||||
|
||||
@@ -173,25 +179,36 @@ public class FilteringTreeBuilder extends AbstractTreeBuilder {
|
||||
selectionDone.setDone();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
TreeUtil.ensureSelection(myTree);
|
||||
selectionDone.setDone();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
selectionDone.setDone();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
queueUpdate().doWhenProcessed(selectionRunnable);
|
||||
} else {
|
||||
selectionRunnable.run();
|
||||
}
|
||||
|
||||
final ActionCallback result = new ActionCallback();
|
||||
|
||||
selectionDone.doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
scrollSelectionToVisible(new Runnable() {
|
||||
public void run() {
|
||||
getReady(this).notify(result);
|
||||
}
|
||||
}, false);
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
scrollSelectionToVisible(new Runnable() {
|
||||
public void run() {
|
||||
getReady(this).notify(result);
|
||||
}
|
||||
}, false);
|
||||
} else {
|
||||
result.setDone();
|
||||
}
|
||||
}
|
||||
}).doWhenRejected(new Runnable() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ public class FilteringTreeStructure extends AbstractTreeStructure {
|
||||
}
|
||||
|
||||
public Object[] getEqualityObjects() {
|
||||
return NONE;
|
||||
return new Object[]{myDelegate};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1040,9 +1040,9 @@ public class FSRecords implements Forceable {
|
||||
}
|
||||
|
||||
private static void checkFileIsValid(int fileId) {
|
||||
assert fileId > 0 : "assert fileId > 0 failed";
|
||||
assert fileId > 0 : fileId;
|
||||
// TODO: This assertion is a bit timey, will remove when bug is caught.
|
||||
assert (getFlags(fileId) & FREE_RECORD_FLAG) == 0 : "Trying to find an attribute of deleted page";
|
||||
assert (getFlags(fileId) & FREE_RECORD_FLAG) == 0 : "Accessing attribute of a deleted page: " + fileId + ":" + getName(fileId);
|
||||
}
|
||||
|
||||
public static int acquireFileContent(int fileId) {
|
||||
|
||||
@@ -528,7 +528,7 @@ exclude.from.imports.no.exclusions=No exclude patterns
|
||||
inline.elements=Inline elements:
|
||||
don.t.break.if.inline.content=Don't break if inline content:
|
||||
edit.code.folding.options=Open code folding options
|
||||
button.new=&New
|
||||
button.new=&New...
|
||||
building.include.indices=Building include indices...
|
||||
loading.include.indices=Loading include indices...
|
||||
use.external.annotations=Use &external annotations
|
||||
|
||||
@@ -295,9 +295,9 @@ module.library.display.name=Module {0, choice, 1#Library|2#Libraries}
|
||||
project.roots.library.banner.text= {1} ''{0}''
|
||||
facet.banner.text=Facet ''{0}''
|
||||
project.roots.project.banner.text=General Settings for Project ''{0}''
|
||||
project.roots.set.up.jdk.title=Set up {0, choice, 1#module|2#project} SDK
|
||||
project.roots.set.up.jdk.title=Set up {0, choice, 1#Module|2#Project} SDK
|
||||
project.roots.no.jdk.on.project.message=Set up created sdk on project?
|
||||
project.roots.no.jdk.on.projecct.title=No project sdk set up
|
||||
project.roots.no.jdk.on.project.title=Create SDK
|
||||
project.roots.jdks.node.text=JDK stands for the Java Development Kit, a software development package that is required to write, test and debug Java applications. \
|
||||
JDK also contains classes and runtime environment that are used to execute the target application. <br><br>\
|
||||
Mobile SDK contains emulator of mobile phone as well as embedded Java SDK to compile/pack/run/debug J2ME applications. <br><br>\
|
||||
|
||||
@@ -313,6 +313,8 @@
|
||||
<extensionPoint name="library.presentationProvider" interface="com.intellij.openapi.roots.libraries.LibraryPresentationProvider"/>
|
||||
<extensionPoint name="library.type" interface="com.intellij.openapi.roots.libraries.LibraryType"/>
|
||||
|
||||
<extensionPoint name="sdkFinder" interface="com.intellij.openapi.roots.impl.ModuleJdkOrderEntryImpl$SdkFinder"/>
|
||||
|
||||
<extensionPoint name="lang.implementationTextSelectioner"
|
||||
beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
<extensionPoint name="lang.lineWrapStrategy"
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,7 +57,7 @@ public class SymLinkHandlingTest extends LightPlatformLangTestCase {
|
||||
assertNull(selfLinkVFile);
|
||||
}
|
||||
|
||||
public void testTargetIsWriteable() throws Exception {
|
||||
public void testTargetIsWritable() throws Exception {
|
||||
if (!SystemInfo.areSymLinksSupported) return;
|
||||
|
||||
final File targetFile = FileUtil.createTempFile("target", "");
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.testFramework;
|
||||
|
||||
import com.intellij.ide.actions.ViewStructureAction;
|
||||
import com.intellij.ide.util.FileStructurePopup;
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
|
||||
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public abstract class FileStructureTestBase extends CodeInsightFixtureTestCase {
|
||||
FileStructurePopup myPopup;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.configureByFile(getFileName(getFileExtension()));
|
||||
myPopup = ViewStructureAction.createPopup(myFixture.getEditor(),
|
||||
myFixture.getProject(),
|
||||
null,
|
||||
TextEditorProvider.getInstance().getTextEditor(myFixture.getEditor()));
|
||||
update();
|
||||
}
|
||||
|
||||
protected abstract String getFileExtension();
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
Disposer.dispose(myPopup);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private String getFileName(String ext) {
|
||||
return getTestName(false) + (StringUtil.isEmpty(ext) ? "" : "." + ext);
|
||||
}
|
||||
|
||||
protected String getTreeFileName() {
|
||||
return getFileName("tree");
|
||||
}
|
||||
|
||||
protected void checkTree() throws Exception {
|
||||
final String expected = FileUtil.loadFile(new File(getTestDataPath() + "/" + getTreeFileName()), true);
|
||||
Assert.assertEquals(expected.trim(), PlatformTestUtil.print(getTree(), true).trim());
|
||||
}
|
||||
|
||||
|
||||
private void update() throws InterruptedException {
|
||||
myPopup.getTreeBuilder().refilter().doWhenProcessed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getStructure().rebuild();
|
||||
updateTree();
|
||||
TreeUtil.expandAll(getTree());
|
||||
final FilteringTreeStructure.FilteringNode node = myPopup.selectPsiElement(myPopup.getCurrentElement(getFile()));
|
||||
getTree().getSelectionModel().setSelectionPath(getTree().getPath(node));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected Tree getTree() {
|
||||
return myPopup.getTree();
|
||||
}
|
||||
|
||||
protected FilteringTreeBuilder getBuilder() {
|
||||
return myPopup.getTreeBuilder();
|
||||
}
|
||||
|
||||
protected TreeSpeedSearch getSpeedSearch() {
|
||||
return myPopup.getSpeedSearch();
|
||||
}
|
||||
|
||||
|
||||
protected void updateTree() {
|
||||
updateRecursively(getRootNode());
|
||||
}
|
||||
|
||||
protected FilteringTreeStructure getStructure() {
|
||||
final FilteringTreeStructure structure = (FilteringTreeStructure)getBuilder().getTreeStructure();
|
||||
assert structure != null;
|
||||
return structure;
|
||||
}
|
||||
|
||||
protected FilteringTreeStructure.FilteringNode getRootNode() {
|
||||
return (FilteringTreeStructure.FilteringNode)getStructure().getRootElement();
|
||||
}
|
||||
|
||||
protected void updateRecursively(final FilteringTreeStructure.FilteringNode node) {
|
||||
node.update();
|
||||
for (FilteringTreeStructure.FilteringNode child : node.children()) {
|
||||
updateRecursively(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.builders.EmptyModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.builders.ModuleFixtureBuilder;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
@@ -29,7 +30,7 @@ import java.io.File;
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public abstract class CodeInsightFixtureTestCase extends UsefulTestCase {
|
||||
public abstract class CodeInsightFixtureTestCase<T extends ModuleFixtureBuilder> extends UsefulTestCase {
|
||||
protected CodeInsightTestFixture myFixture;
|
||||
protected Module myModule;
|
||||
|
||||
@@ -39,7 +40,7 @@ public abstract class CodeInsightFixtureTestCase extends UsefulTestCase {
|
||||
|
||||
final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder();
|
||||
myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());
|
||||
final EmptyModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(EmptyModuleFixtureBuilder.class);
|
||||
final T moduleFixtureBuilder = projectBuilder.addModule(getModuleBuilderClass());
|
||||
moduleFixtureBuilder.addSourceContentRoot(myFixture.getTempDirPath());
|
||||
tuneFixture(moduleFixtureBuilder);
|
||||
|
||||
@@ -48,6 +49,10 @@ public abstract class CodeInsightFixtureTestCase extends UsefulTestCase {
|
||||
myModule = moduleFixtureBuilder.getFixture().getModule();
|
||||
}
|
||||
|
||||
protected Class<T> getModuleBuilderClass() {
|
||||
return (Class<T>)EmptyModuleFixtureBuilder.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myFixture.tearDown();
|
||||
@@ -56,7 +61,7 @@ public abstract class CodeInsightFixtureTestCase extends UsefulTestCase {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected void tuneFixture(final EmptyModuleFixtureBuilder moduleBuilder) {}
|
||||
protected void tuneFixture(final T moduleBuilder) {}
|
||||
|
||||
/**
|
||||
* Return relative path to the test data. Path is relative to the
|
||||
|
||||
@@ -173,12 +173,23 @@ public class FileUtil {
|
||||
|
||||
@NotNull
|
||||
public static String loadFile(@NotNull File file) throws IOException {
|
||||
return loadFile(file, null);
|
||||
return loadFile(file, null, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String loadFile(@NotNull File file, boolean convertLineSeparators) throws IOException {
|
||||
return loadFile(file, null, convertLineSeparators);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String loadFile(@NotNull File file, String encoding) throws IOException {
|
||||
return new String(loadFileText(file, encoding));
|
||||
return loadFile(file, encoding, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String loadFile(@NotNull File file, String encoding, boolean convertLineSeparators) throws IOException {
|
||||
final String s = new String(loadFileText(file, encoding));
|
||||
return convertLineSeparators ? StringUtil.convertLineSeparators(s) : s;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -92,5 +92,10 @@ public class ConcurrentHashSet<K> implements Set<K> {
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return map.keySet().toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PagedFileStorage implements Forceable {
|
||||
|
||||
static {
|
||||
final int lower = 100;
|
||||
final int upper = SystemInfo.is64Bit ? 500 : 200;
|
||||
final int upper = SystemInfo.is64Bit && !PersistentEnumeratorDelegate.useBtree() ? 500 : 200;
|
||||
|
||||
BUFFER_SIZE = Math.max(1, SystemInfo.getIntProperty("idea.paged.storage.page.size", 10)) * MB;
|
||||
if (ByteBufferWrapper.NO_MMAP) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.Forceable;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.Closeable;
|
||||
@@ -32,7 +31,7 @@ public class PersistentEnumeratorDelegate<Data> implements Closeable, Forceable
|
||||
new PersistentEnumerator<Data>(file, dataDescriptor, initialSize);
|
||||
}
|
||||
|
||||
private boolean useBtree() {
|
||||
static boolean useBtree() {
|
||||
String property = System.getProperty("idea.use.btree");
|
||||
return !"false".equals(property);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
@@ -51,7 +53,7 @@ public class SmallMapSerializer<K,V> implements Forceable {
|
||||
private void init() {
|
||||
try {
|
||||
final byte[] bytes = FileUtil.loadFileBytes(myFile);
|
||||
final DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
|
||||
final DataInputStream dis = new DataInputStream(new UnsyncByteArrayInputStream(bytes));
|
||||
final int size = dis.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final KeyWrapper<K> keyWrapper = new KeyWrapper<K>(myKeyDescriptor, myKeyDescriptor.read(dis));
|
||||
|
||||
+59
-6
@@ -31,6 +31,7 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -45,25 +46,29 @@ import org.jetbrains.idea.eclipse.config.EclipseModuleManager;
|
||||
import org.jetbrains.idea.eclipse.importWizard.EclipseProjectFinder;
|
||||
import org.jetbrains.idea.eclipse.util.ErrorLog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import static org.jetbrains.idea.eclipse.conversion.EPathUtil.*;
|
||||
import static org.jetbrains.idea.eclipse.conversion.EPathUtil.expandEclipsePath2Url;
|
||||
|
||||
public class EclipseClasspathReader {
|
||||
private final String myRootPath;
|
||||
private final Project myProject;
|
||||
@Nullable private final List<String> myCurrentRoots;
|
||||
private ContentEntry myContentEntry;
|
||||
@Nullable private final Set<String> myModuleNames;
|
||||
|
||||
public EclipseClasspathReader(final String rootPath, final Project project, @Nullable List<String> currentRoots) {
|
||||
this(rootPath, project, currentRoots, null);
|
||||
}
|
||||
|
||||
public EclipseClasspathReader(final String rootPath, final Project project, @Nullable List<String> currentRoots, @Nullable Set<String> moduleNames) {
|
||||
myRootPath = FileUtil.toSystemIndependentName(rootPath);
|
||||
myProject = project;
|
||||
myCurrentRoots = currentRoots;
|
||||
myModuleNames = moduleNames;
|
||||
}
|
||||
|
||||
public void init(ModifiableRootModel model) {
|
||||
@@ -236,6 +241,7 @@ public class EclipseClasspathReader {
|
||||
}
|
||||
else if (kind.equals(EclipseXml.CON_KIND)) {
|
||||
if (path.equals(EclipseXml.ECLIPSE_PLATFORM)) {
|
||||
readRequiredBundles(rootModel, refsToModules);
|
||||
addNamedLibrary(rootModel, unknownLibraries, exported, IdeaXml.ECLIPSE_LIBRARY, LibraryTablesRegistrar.APPLICATION_LEVEL);
|
||||
}
|
||||
else if (path.startsWith(EclipseXml.JRE_CONTAINER)) {
|
||||
@@ -276,6 +282,53 @@ public class EclipseClasspathReader {
|
||||
}
|
||||
}
|
||||
|
||||
private void readRequiredBundles(ModifiableRootModel rootModel, Set<String> refsToModules) throws ConversionException {
|
||||
if (myModuleNames == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final File manifestFile = new File(myRootPath, "META-INF/MANIFEST.MF");
|
||||
if (!manifestFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new BufferedInputStream(new FileInputStream(manifestFile));
|
||||
final Manifest manifest = new Manifest(in);
|
||||
final String attributes = manifest.getMainAttributes().getValue("Require-Bundle");
|
||||
if (!StringUtil.isEmpty(attributes)) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(attributes, ",");
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String bundle = tokenizer.nextToken().trim();
|
||||
if (!bundle.isEmpty()) {
|
||||
final int constraintIndex = bundle.indexOf(';');
|
||||
if (constraintIndex != -1) {
|
||||
bundle = bundle.substring(0, constraintIndex).trim();
|
||||
}
|
||||
|
||||
if (myModuleNames.contains(bundle)) {
|
||||
refsToModules.add(bundle);
|
||||
rootModel.addInvalidModuleEntry(bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ConversionException(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int rearrangeOrderEntryOfType(ModifiableRootModel rootModel, Class<? extends OrderEntry> orderEntryClass) {
|
||||
OrderEntry[] orderEntries = rootModel.getOrderEntries();
|
||||
int moduleSourcesIdx = 0;
|
||||
|
||||
+4
-1
@@ -50,6 +50,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
|
||||
import com.intellij.projectImport.ProjectImportBuilder;
|
||||
import com.intellij.util.Function;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -198,12 +199,14 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
|
||||
final ModifiableModuleModel moduleModel = model != null ? model : ModuleManager.getInstance(project).getModifiableModel();
|
||||
final ModifiableRootModel[] rootModels = new ModifiableRootModel[getParameters().projectsToConvert.size()];
|
||||
final Set<File> files = new HashSet<File>();
|
||||
final Set<String> moduleNames = new THashSet<String>(getParameters().projectsToConvert.size());
|
||||
for (String path : getParameters().projectsToConvert) {
|
||||
String modulesDirectory = getParameters().converterOptions.commonModulesDirectory;
|
||||
if (modulesDirectory == null) {
|
||||
modulesDirectory = path;
|
||||
}
|
||||
final String moduleName = EclipseProjectFinder.findProjectName(path);
|
||||
moduleNames.add(moduleName);
|
||||
final File imlFile = new File(modulesDirectory + File.separator + moduleName + IdeaXml.IML_EXT);
|
||||
if (imlFile.isFile()) {
|
||||
files.add(imlFile);
|
||||
@@ -266,7 +269,7 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
|
||||
rootModels[idx++] = rootModel;
|
||||
|
||||
final File classpathFile = new File(path, EclipseXml.DOT_CLASSPATH_EXT);
|
||||
final EclipseClasspathReader classpathReader = new EclipseClasspathReader(path, project, getParameters().projectsToConvert);
|
||||
final EclipseClasspathReader classpathReader = new EclipseClasspathReader(path, project, getParameters().projectsToConvert, moduleNames);
|
||||
classpathReader.init(rootModel);
|
||||
if (classpathFile.exists()) {
|
||||
final Element classpathElement = JDOMUtil.loadDocument(classpathFile).getRootElement();
|
||||
|
||||
@@ -37,6 +37,8 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.pluralize;
|
||||
|
||||
/**
|
||||
* Common class for Git operations with branches aware of multi-root configuration,
|
||||
* which means showing combined error information, proposing to rollback, etc.
|
||||
@@ -154,7 +156,7 @@ abstract class GitBranchOperation {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String description = message + getRollbackProposal();
|
||||
String description = "<html>" + message + ".<br/>" + getRollbackProposal() + "</html>";
|
||||
ok.set(Messages.OK ==
|
||||
MessageManager.showYesNoDialog(myProject, description, title, "Rollback", "Don't rollback", Messages.getErrorIcon()));
|
||||
}
|
||||
@@ -190,11 +192,16 @@ abstract class GitBranchOperation {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String repositories() {
|
||||
return pluralize("repository", getSuccessfulRepositories().size());
|
||||
}
|
||||
|
||||
private void showUnmergedFilesDialogWithRollback() {
|
||||
final AtomicBoolean ok = new AtomicBoolean();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override public void run() {
|
||||
String description = "You have to resolve all merge conflicts before checkout.<br/>" + getRollbackProposal();
|
||||
String description = "<html>You have to resolve all merge conflicts before checkout.<br/>" + getRollbackProposal() + "</html>";
|
||||
// suppressing: this message looks ugly if capitalized by words
|
||||
//noinspection DialogTitleCapitalization
|
||||
ok.set(Messages.OK == MessageManager.showYesNoDialog(myProject, description, UNMERGED_FILES_ERROR_TITLE, "Rollback", "Don't rollback", Messages.getErrorIcon()));
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -52,7 +51,7 @@ public final class GitBranchOperationsProcessor {
|
||||
private static final Logger LOG = Logger.getInstance(GitBranchOperationsProcessor.class);
|
||||
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
@Nullable private final Runnable myCallInAwtAfterExecution;
|
||||
private final GitRepository mySelectedRepository;
|
||||
|
||||
@@ -61,16 +60,16 @@ public final class GitBranchOperationsProcessor {
|
||||
}
|
||||
|
||||
public GitBranchOperationsProcessor(@NotNull GitRepository repository, @Nullable Runnable callInAwtAfterExecution) {
|
||||
this(repository.getProject(), Collections.singleton(repository), repository, callInAwtAfterExecution);
|
||||
this(repository.getProject(), Collections.singletonList(repository), repository, callInAwtAfterExecution);
|
||||
}
|
||||
|
||||
public GitBranchOperationsProcessor(@NotNull Project project, @NotNull Collection<GitRepository> repositories,
|
||||
public GitBranchOperationsProcessor(@NotNull Project project, @NotNull List<GitRepository> repositories,
|
||||
@NotNull GitRepository selectedRepository) {
|
||||
this(project, repositories, selectedRepository, null);
|
||||
}
|
||||
|
||||
public GitBranchOperationsProcessor(@NotNull Project project,
|
||||
@NotNull Collection<GitRepository> repositories,
|
||||
@NotNull List<GitRepository> repositories,
|
||||
@NotNull GitRepository selectedRepository,
|
||||
@Nullable Runnable callInAwtAfterExecution) {
|
||||
myProject = project;
|
||||
@@ -205,7 +204,7 @@ public final class GitBranchOperationsProcessor {
|
||||
}.runInBackground();
|
||||
}
|
||||
|
||||
private GitCommitCompareInfo loadCommitsToCompare(Collection<GitRepository> repositories, String branchName) {
|
||||
private GitCommitCompareInfo loadCommitsToCompare(List<GitRepository> repositories, String branchName) {
|
||||
GitCommitCompareInfo compareInfo = new GitCommitCompareInfo();
|
||||
for (GitRepository repository : repositories) {
|
||||
compareInfo.put(repository, loadCommitsToCompare(repository, branchName));
|
||||
|
||||
@@ -93,7 +93,7 @@ public class GitCheckoutNewBranchOperation extends GitBranchOperation {
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getRollbackProposal() {
|
||||
return "However checkout has succeeded for the following repositories:<br/>" +
|
||||
return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
|
||||
successfulRepositoriesJoined() +
|
||||
"<br/>You may rollback (checkout back to " + myPreviousBranch + ") not to let branches diverge.";
|
||||
}
|
||||
@@ -104,7 +104,7 @@ public class GitCheckoutNewBranchOperation extends GitBranchOperation {
|
||||
GitCompoundResult deleteResult = new GitCompoundResult(myProject);
|
||||
Collection<GitRepository> repositories = getSuccessfulRepositories();
|
||||
for (GitRepository repository : repositories) {
|
||||
GitCommandResult result = Git.checkout(repository, myPreviousBranch, null);
|
||||
GitCommandResult result = Git.checkout(repository, myPreviousBranch, null, true);
|
||||
checkoutResult.append(repository, result);
|
||||
if (result.success()) {
|
||||
deleteResult.append(repository, Git.branchDelete(repository, myNewBranchName, false));
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.Clock;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
@@ -55,6 +54,7 @@ import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.*;
|
||||
import static git4idea.commands.GitMessageWithFilesDetector.Event.LOCAL_CHANGES_OVERWRITTEN_BY_CHECKOUT;
|
||||
import static git4idea.commands.GitMessageWithFilesDetector.Event.UNTRACKED_FILES_OVERWRITTEN_BY;
|
||||
import static git4idea.util.GitUIUtil.code;
|
||||
@@ -96,7 +96,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
GitSimpleEventDetector unmergedFiles = new GitSimpleEventDetector(GitSimpleEventDetector.Event.UNMERGED);
|
||||
GitMessageWithFilesDetector untrackedOverwrittenByCheckout = new GitMessageWithFilesDetector(UNTRACKED_FILES_OVERWRITTEN_BY, root);
|
||||
|
||||
GitCommandResult result = Git.checkout(repository, myStartPointReference, myNewBranch,
|
||||
GitCommandResult result = Git.checkout(repository, myStartPointReference, myNewBranch, false,
|
||||
localChangesOverwrittenByCheckout, unmergedFiles, untrackedOverwrittenByCheckout);
|
||||
if (result.success()) {
|
||||
refresh(repository);
|
||||
@@ -134,13 +134,14 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
// get all other conflicting changes
|
||||
Map<GitRepository, List<Change>> conflictingChangesInRepositories = collectLocalChangesOnAllOtherRepositories(repository);
|
||||
Set<GitRepository> otherProblematicRepositories = conflictingChangesInRepositories.keySet();
|
||||
Collection<GitRepository> allConflictingRepositories = new ArrayList<GitRepository>(otherProblematicRepositories);
|
||||
List<GitRepository> allConflictingRepositories = new ArrayList<GitRepository>(otherProblematicRepositories);
|
||||
allConflictingRepositories.add(repository);
|
||||
for (List<Change> changes : conflictingChangesInRepositories.values()) {
|
||||
affectedChanges.addAll(changes);
|
||||
}
|
||||
|
||||
if (GitWouldBeOverwrittenByCheckoutDialog.showAndGetAnswer(myProject, affectedChanges)) {
|
||||
int smartCheckoutDecision = GitWouldBeOverwrittenByCheckoutDialog.showAndGetAnswer(myProject, affectedChanges);
|
||||
if (smartCheckoutDecision == GitWouldBeOverwrittenByCheckoutDialog.SMART_CHECKOUT) {
|
||||
boolean smartCheckedOutSuccessfully = smartCheckout(allConflictingRepositories, myStartPointReference, myNewBranch, getIndicator());
|
||||
if (smartCheckedOutSuccessfully) {
|
||||
GitRepository[] otherRepositories = ArrayUtil.toObjectArray(otherProblematicRepositories, GitRepository.class);
|
||||
@@ -156,6 +157,9 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (smartCheckoutDecision == GitWouldBeOverwrittenByCheckoutDialog.FORCE_CHECKOUT_EXIT_CODE) {
|
||||
return checkoutOrNotify(allConflictingRepositories, myStartPointReference, myNewBranch, true);
|
||||
}
|
||||
else {
|
||||
fatalLocalChangesError();
|
||||
return false;
|
||||
@@ -203,7 +207,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
String description = UntrackedFilesNotifier.createUntrackedFilesOverwrittenDescription("checkout", true);
|
||||
|
||||
final SelectFilesDialog dialog = new UntrackedFilesDialog(myProject, new ArrayList<VirtualFile>(untrackedFiles),
|
||||
StringUtil.stripHtml(description, true));
|
||||
stripHtml(description, true));
|
||||
dialog.setTitle(title);
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
@@ -238,7 +242,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getRollbackProposal() {
|
||||
return "However checkout has succeeded for the following repositories:<br/>" +
|
||||
return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
|
||||
successfulRepositoriesJoined() +
|
||||
"<br/>You may rollback (checkout back to " + myPreviousBranch + ") not to let branches diverge.";
|
||||
}
|
||||
@@ -248,7 +252,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
GitCompoundResult checkoutResult = new GitCompoundResult(myProject);
|
||||
GitCompoundResult deleteResult = new GitCompoundResult(myProject);
|
||||
for (GitRepository repository : getSuccessfulRepositories()) {
|
||||
GitCommandResult result = Git.checkout(repository, myPreviousBranch, null);
|
||||
GitCommandResult result = Git.checkout(repository, myPreviousBranch, null, true);
|
||||
checkoutResult.append(repository, result);
|
||||
if (result.success() && myNewBranch != null) {
|
||||
/*
|
||||
@@ -310,7 +314,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
}
|
||||
|
||||
// stash - checkout - unstash
|
||||
private boolean smartCheckout(@NotNull final Collection<GitRepository> repositories, @NotNull final String reference, @Nullable final String newBranch, @NotNull ProgressIndicator indicator) {
|
||||
private boolean smartCheckout(@NotNull final List<GitRepository> repositories, @NotNull final String reference, @Nullable final String newBranch, @NotNull ProgressIndicator indicator) {
|
||||
final GitChangesSaver saver = configureSaver(reference, indicator);
|
||||
|
||||
final AtomicBoolean result = new AtomicBoolean();
|
||||
@@ -319,7 +323,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
boolean savedSuccessfully = save(repositories, saver);
|
||||
if (savedSuccessfully) {
|
||||
try {
|
||||
result.set(checkoutOrNotify(repositories, reference, newBranch));
|
||||
result.set(checkoutOrNotify(repositories, reference, newBranch, false));
|
||||
} finally {
|
||||
saver.restoreLocalChanges(context);
|
||||
}
|
||||
@@ -376,7 +380,7 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
LOG.info("Couldn't save local changes", e);
|
||||
notifyError("Couldn't save uncommitted changes.",
|
||||
String.format("Tried to save uncommitted changes in %s before checkout, but failed with an error.<br/>%s",
|
||||
saver.getSaverName(), StringUtil.join(e.getMessages())));
|
||||
saver.getSaverName(), join(e.getMessages())));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -384,12 +388,11 @@ public class GitCheckoutOperation extends GitBranchOperation {
|
||||
/**
|
||||
* Checks out or shows an error message.
|
||||
*/
|
||||
private boolean checkoutOrNotify(@NotNull Collection<GitRepository> repositories,
|
||||
@NotNull String reference,
|
||||
@Nullable String newBranch) {
|
||||
private boolean checkoutOrNotify(@NotNull List<GitRepository> repositories,
|
||||
@NotNull String reference, @Nullable String newBranch, boolean force) {
|
||||
GitCompoundResult compoundResult = new GitCompoundResult(myProject);
|
||||
for (GitRepository repository : repositories) {
|
||||
compoundResult.append(repository, Git.checkout(repository, reference, newBranch));
|
||||
compoundResult.append(repository, Git.checkout(repository, reference, newBranch, force));
|
||||
}
|
||||
if (compoundResult.totalSuccess()) {
|
||||
return true;
|
||||
|
||||
@@ -137,7 +137,7 @@ class GitDeleteBranchOperation extends GitBranchOperation {
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getRollbackProposal() {
|
||||
return "However branch deletion has succeeded for the following repositories.:<br/>" +
|
||||
return "However branch deletion has succeeded for the following " + repositories() + ":<br/>" +
|
||||
successfulRepositoriesJoined() +
|
||||
"<br/>You may rollback (recreate " + myBranchName + " in these roots) not to let branches diverge.";
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@ import git4idea.DialogManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* The dialog that is shown when the error "The following files would be overwritten by checkout" happens.
|
||||
@@ -38,23 +39,26 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
// TODO "don't ask again" option
|
||||
class GitWouldBeOverwrittenByCheckoutDialog extends DialogWrapper {
|
||||
|
||||
public static final int SMART_CHECKOUT = OK_EXIT_CODE;
|
||||
public static final int FORCE_CHECKOUT_EXIT_CODE = NEXT_USER_EXIT_CODE;
|
||||
|
||||
private final Project myProject;
|
||||
private final List<Change> myChanges;
|
||||
|
||||
/**
|
||||
* @return true if smart checkout has to be performed, false if user doesn't want to checkout.
|
||||
*/
|
||||
static boolean showAndGetAnswer(@NotNull final Project project, @NotNull final List<Change> changes) {
|
||||
final AtomicBoolean ok = new AtomicBoolean();
|
||||
static int showAndGetAnswer(@NotNull final Project project, @NotNull final List<Change> changes) {
|
||||
final AtomicInteger exitCode = new AtomicInteger();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
GitWouldBeOverwrittenByCheckoutDialog dialog = new GitWouldBeOverwrittenByCheckoutDialog(project, changes);
|
||||
DialogManager.getInstance(project).showDialog(dialog);
|
||||
ok.set(dialog.isOK());
|
||||
exitCode.set(dialog.getExitCode());
|
||||
}
|
||||
});
|
||||
return ok.get();
|
||||
return exitCode.get();
|
||||
}
|
||||
|
||||
private GitWouldBeOverwrittenByCheckoutDialog(@NotNull Project project, @NotNull List<Change> changes) {
|
||||
@@ -68,8 +72,8 @@ class GitWouldBeOverwrittenByCheckoutDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Action getOKAction() {
|
||||
return super.getOKAction();
|
||||
protected Action[] createLeftSideActions() {
|
||||
return new Action[] {new ForceCheckoutAction() };
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,4 +97,17 @@ class GitWouldBeOverwrittenByCheckoutDialog extends DialogWrapper {
|
||||
return GitWouldBeOverwrittenByCheckoutDialog.class.getName();
|
||||
}
|
||||
|
||||
|
||||
private class ForceCheckoutAction extends AbstractAction {
|
||||
|
||||
ForceCheckoutAction() {
|
||||
super("Force checkout");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
close(FORCE_CHECKOUT_EXIT_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -138,12 +138,17 @@ public class Git {
|
||||
public static GitCommandResult checkout(@NotNull GitRepository repository,
|
||||
@NotNull String reference,
|
||||
@Nullable String newBranch,
|
||||
boolean force,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.CHECKOUT);
|
||||
h.setSilent(false);
|
||||
if (force) {
|
||||
h.addParameters("--force");
|
||||
}
|
||||
if (newBranch == null) { // simply checkout
|
||||
h.addParameters(reference);
|
||||
} else { // checkout reference as new branch
|
||||
}
|
||||
else { // checkout reference as new branch
|
||||
h.addParameters("-b", newBranch, reference);
|
||||
}
|
||||
for (GitLineHandlerListener listener : listeners) {
|
||||
|
||||
@@ -502,8 +502,8 @@ public abstract class GitHandler {
|
||||
public void setSilent(final boolean silent) {
|
||||
checkNotStarted();
|
||||
mySilent = silent;
|
||||
setStderrSuppressed(true);
|
||||
setStdoutSuppressed(true);
|
||||
setStderrSuppressed(silent);
|
||||
setStdoutSuppressed(silent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
class GitPushRejectedDetector implements GitLineHandlerListener {
|
||||
|
||||
private static final Pattern REJECTED_PATTERN = Pattern.compile("\\s+! \\[rejected\\]\\s+(\\w+) -> (\\w+) .*");
|
||||
private static final Pattern REJECTED_PATTERN = Pattern.compile("\\s+! \\[rejected\\]\\s+(\\S+) -> (\\S+) .*");
|
||||
|
||||
private final Collection<RejectedRef> myRejectedRefs = new ArrayList<RejectedRef>();
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static git4idea.GitUtil.sortRepositories;
|
||||
|
||||
/**
|
||||
* GitRepositoryManager initializes and stores {@link GitRepository GitRepositories} for Git roots defined in the project.
|
||||
* @author Kirill Likhodedov
|
||||
@@ -152,10 +154,10 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme
|
||||
* @return all repositories tracked by the manager.
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<GitRepository> getRepositories() {
|
||||
public List<GitRepository> getRepositories() {
|
||||
try {
|
||||
REPO_LOCK.readLock().lock();
|
||||
return myRepositories.values();
|
||||
return sortRepositories(myRepositories.values());
|
||||
}
|
||||
finally {
|
||||
REPO_LOCK.readLock().unlock();
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -65,12 +65,9 @@ class GitBranchPopup {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param project
|
||||
* @param currentRepository Current repository, which means the repository of the currently open or selected file.
|
||||
* In the case of synchronized branch operations current repository matter much less, but sometimes is used,
|
||||
* for example, it is preselected in the repositories combobox in the compare branches dialog.
|
||||
* @return
|
||||
*/
|
||||
static GitBranchPopup getInstance(@NotNull Project project, @NotNull GitRepository currentRepository) {
|
||||
return new GitBranchPopup(project, currentRepository);
|
||||
@@ -157,7 +154,7 @@ class GitBranchPopup {
|
||||
}
|
||||
|
||||
private void fillWithCommonRepositoryActions(DefaultActionGroup popupGroup, GitRepositoryManager repositoryManager) {
|
||||
Collection<GitRepository> repositories = repositoryManager.getRepositories();
|
||||
List<GitRepository> repositories = repositoryManager.getRepositories();
|
||||
String currentBranch = myMultiRootBranchConfig.getCurrentBranch();
|
||||
assert currentBranch != null : "Current branch can't be null if branches have not diverged";
|
||||
popupGroup.add(new GitBranchPopupActions.CurrentBranchAction(currentBranch, " in all roots"));
|
||||
|
||||
@@ -33,7 +33,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;
|
||||
|
||||
@@ -56,7 +55,7 @@ class GitBranchPopupActions {
|
||||
DefaultActionGroup popupGroup = new DefaultActionGroup(null, false);
|
||||
|
||||
popupGroup.addAction(new CurrentBranchAction(GitBranchUiUtil.getDisplayableBranchText(myRepository), "in root " + GitUIUtil.getShortRepositoryName(myRepository)));
|
||||
popupGroup.addAction(new NewBranchAction(myProject, Collections.singleton(myRepository), myRepository));
|
||||
popupGroup.addAction(new NewBranchAction(myProject, Collections.singletonList(myRepository), myRepository));
|
||||
popupGroup.addAction(new CheckoutRevisionActions(myProject, myRepository));
|
||||
|
||||
if (toInsert != null) {
|
||||
@@ -68,7 +67,7 @@ class GitBranchPopupActions {
|
||||
Collections.sort(localBranches);
|
||||
for (GitBranch localBranch : localBranches) {
|
||||
if (!localBranch.equals(myRepository.getCurrentBranch())) { // don't show current branch in the list
|
||||
popupGroup.add(new LocalBranchActions(myProject, Collections.singleton(myRepository), localBranch.getName(), myRepository));
|
||||
popupGroup.add(new LocalBranchActions(myProject, Collections.singletonList(myRepository), localBranch.getName(), myRepository));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +75,7 @@ class GitBranchPopupActions {
|
||||
List<GitBranch> remoteBranches = new ArrayList<GitBranch>(myRepository.getBranches().getRemoteBranches());
|
||||
Collections.sort(remoteBranches);
|
||||
for (GitBranch remoteBranch : remoteBranches) {
|
||||
popupGroup.add(new RemoteBranchActions(myProject, Collections.singleton(myRepository), remoteBranch.getName(), myRepository));
|
||||
popupGroup.add(new RemoteBranchActions(myProject, Collections.singletonList(myRepository), remoteBranch.getName(), myRepository));
|
||||
}
|
||||
|
||||
return popupGroup;
|
||||
@@ -101,10 +100,10 @@ class GitBranchPopupActions {
|
||||
|
||||
static class NewBranchAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
@NotNull private final GitRepository mySelectedRepository;
|
||||
|
||||
NewBranchAction(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull GitRepository selectedRepository) {
|
||||
NewBranchAction(@NotNull Project project, @NotNull List<GitRepository> repositories, @NotNull GitRepository selectedRepository) {
|
||||
super("New Branch", "Create and checkout new branch", IconLoader.getIcon("/general/add.png"));
|
||||
myProject = project;
|
||||
myRepositories = repositories;
|
||||
@@ -175,11 +174,11 @@ class GitBranchPopupActions {
|
||||
static class LocalBranchActions extends ActionGroup {
|
||||
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private String myBranchName;
|
||||
@NotNull private final GitRepository mySelectedRepository;
|
||||
|
||||
LocalBranchActions(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String branchName,
|
||||
LocalBranchActions(@NotNull Project project, @NotNull List<GitRepository> repositories, @NotNull String branchName,
|
||||
@NotNull GitRepository selectedRepository) {
|
||||
super("", true);
|
||||
myProject = project;
|
||||
@@ -202,11 +201,11 @@ class GitBranchPopupActions {
|
||||
|
||||
private static class CheckoutAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private final String myBranchName;
|
||||
@NotNull private final GitRepository mySelectedRepository;
|
||||
|
||||
CheckoutAction(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String branchName,
|
||||
CheckoutAction(@NotNull Project project, @NotNull List<GitRepository> repositories, @NotNull String branchName,
|
||||
@NotNull GitRepository selectedRepository) {
|
||||
super("Checkout");
|
||||
myProject = project;
|
||||
@@ -224,11 +223,11 @@ class GitBranchPopupActions {
|
||||
|
||||
private static class CheckoutAsNewBranch extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private final String myBranchName;
|
||||
@NotNull private final GitRepository mySelectedRepository;
|
||||
|
||||
CheckoutAsNewBranch(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String branchName,
|
||||
CheckoutAsNewBranch(@NotNull Project project, @NotNull List<GitRepository> repositories, @NotNull String branchName,
|
||||
@NotNull GitRepository selectedRepository) {
|
||||
super("Checkout as new branch");
|
||||
myProject = project;
|
||||
@@ -254,11 +253,11 @@ class GitBranchPopupActions {
|
||||
*/
|
||||
private static class DeleteAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private final String myBranchName;
|
||||
private final GitRepository mySelectedRepository;
|
||||
|
||||
DeleteAction(Project project, Collection<GitRepository> repositories, String branchName, GitRepository selectedRepository) {
|
||||
DeleteAction(Project project, List<GitRepository> repositories, String branchName, GitRepository selectedRepository) {
|
||||
super("Delete");
|
||||
myProject = project;
|
||||
myRepositories = repositories;
|
||||
@@ -279,11 +278,11 @@ class GitBranchPopupActions {
|
||||
static class RemoteBranchActions extends ActionGroup {
|
||||
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private String myBranchName;
|
||||
@NotNull private final GitRepository mySelectedRepository;
|
||||
|
||||
RemoteBranchActions(@NotNull Project project, @NotNull Collection<GitRepository> repositories, @NotNull String branchName,
|
||||
RemoteBranchActions(@NotNull Project project, @NotNull List<GitRepository> repositories, @NotNull String branchName,
|
||||
@NotNull GitRepository selectedRepository) {
|
||||
super("", true);
|
||||
myProject = project;
|
||||
@@ -304,11 +303,11 @@ class GitBranchPopupActions {
|
||||
|
||||
private static class CheckoutRemoteBranchAction extends DumbAwareAction {
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private final String myRemoteBranchName;
|
||||
@NotNull private final GitRepository mySelectedRepository;
|
||||
|
||||
public CheckoutRemoteBranchAction(@NotNull Project project, @NotNull Collection<GitRepository> repositories,
|
||||
public CheckoutRemoteBranchAction(@NotNull Project project, @NotNull List<GitRepository> repositories,
|
||||
@NotNull String remoteBranchName, @NotNull GitRepository selectedRepository) {
|
||||
super("Checkout as new local branch");
|
||||
myProject = project;
|
||||
@@ -339,12 +338,12 @@ class GitBranchPopupActions {
|
||||
private static class CompareAction extends DumbAwareAction {
|
||||
|
||||
private final Project myProject;
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
private final String myBranchName;
|
||||
private final GitRepository mySelectedRepository;
|
||||
|
||||
public CompareAction(@NotNull Project project,
|
||||
@NotNull Collection<GitRepository> repositories,
|
||||
@NotNull List<GitRepository> repositories,
|
||||
@NotNull String branchName,
|
||||
GitRepository selectedRepository) {
|
||||
super("Compare");
|
||||
|
||||
@@ -24,15 +24,16 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitMultiRootBranchConfig {
|
||||
|
||||
private final Collection<GitRepository> myRepositories;
|
||||
private final List<GitRepository> myRepositories;
|
||||
|
||||
public GitMultiRootBranchConfig(@NotNull Collection<GitRepository> repositories) {
|
||||
public GitMultiRootBranchConfig(@NotNull List<GitRepository> repositories) {
|
||||
myRepositories = repositories;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static git4idea.test.GitExec.*;
|
||||
@@ -51,7 +51,7 @@ public class GitBranchOperationsTest extends AbstractVcsTestCase {
|
||||
private static final String NEW_BRANCH = "new_branch";
|
||||
private static final String MASTER = "master";
|
||||
|
||||
private Collection<GitRepository> myRepositories;
|
||||
private List<GitRepository> myRepositories;
|
||||
private GitRepository myUltimate;
|
||||
private GitRepository myCommunity;
|
||||
private GitRepository myContrib;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 529 B After Width: | Height: | Size: 500 B |
@@ -36,7 +36,12 @@
|
||||
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.remote.GradleApiFacadeManager"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.util.GradleLibraryManager"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangesCalculator"/>
|
||||
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator"
|
||||
serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangesCalculator"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleModuleStructureChangesCalculator"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleLibraryDependencyStructureChangesCalculator"/>
|
||||
<applicationService serviceInterface="org.jetbrains.plugins.gradle.diff.GradleProjectStructureHelper"
|
||||
serviceImplementation="org.jetbrains.plugins.gradle.diff.GradleProjectStructureHelperImpl"/>
|
||||
<applicationService serviceInterface="org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager"
|
||||
serviceImplementation="org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl"/>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.plugins.gradle.ui.GradleIcons;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
* Encapsulates initialisation routine of the gradle integration.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 11/3/11 4:01 PM
|
||||
@@ -42,10 +42,6 @@ public class GradleBootstrap extends AbstractProjectComponent {
|
||||
}
|
||||
|
||||
private void initToolWindow() {
|
||||
// TODO den don't show tool window if no gradle project is associated with the current project.
|
||||
if (!Boolean.getBoolean("gradle.show.tool.window")) {
|
||||
return;
|
||||
}
|
||||
final ToolWindowManagerEx manager = ToolWindowManagerEx.getInstanceEx(myProject);
|
||||
ToolWindow toolWindow = manager.registerToolWindow(GRADLE_TOOL_WINDOW_ID, false, ToolWindowAnchor.RIGHT);
|
||||
toolWindow.setIcon(GradleIcons.GRADLE_ICON);
|
||||
|
||||
@@ -25,11 +25,10 @@ public class GradleDiffUtil {
|
||||
* Example: particular module has been added at the gradle side. We want to mark that module, its content root(s), dependencies etc
|
||||
* as gradle-local changes.
|
||||
*
|
||||
* @param entity target gradle-local entity
|
||||
* @return collection of gradle-local changes for the given entity and its interested sub-entities
|
||||
* @param entity target gradle-local entity
|
||||
* @param currentChanges holder for the changes built during the current call
|
||||
*/
|
||||
public static Set<GradleProjectStructureChange> buildLocalChanges(@NotNull GradleEntity entity) {
|
||||
final Set<GradleProjectStructureChange> result = new HashSet<GradleProjectStructureChange>();
|
||||
public static void buildLocalChanges(@NotNull GradleEntity entity, @NotNull final Set<GradleProjectStructureChange> currentChanges) {
|
||||
entity.invite(new GradleEntityVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull GradleProject project) {
|
||||
@@ -38,7 +37,7 @@ public class GradleDiffUtil {
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull GradleModule module) {
|
||||
result.add(new GradleModulePresenceChange(module, null));
|
||||
currentChanges.add(new GradleModulePresenceChange(module, null));
|
||||
for (GradleDependency dependency : module.getDependencies()) {
|
||||
dependency.invite(this);
|
||||
}
|
||||
@@ -61,79 +60,52 @@ public class GradleDiffUtil {
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull GradleLibraryDependency dependency) {
|
||||
result.add(new GradleLibraryDependencyPresenceChange(dependency, null));
|
||||
currentChanges.add(new GradleLibraryDependencyPresenceChange(dependency, null));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analogues to {@link #buildLocalChanges} but targets intellij entity.
|
||||
*
|
||||
* @param module target intellij-local module that doesn't present at the gradle side
|
||||
* @return collection of intellij-local changes for the given entity and its interested sub-entities
|
||||
* @param module target intellij-local module that doesn't present at the gradle side
|
||||
* @param currentChanges holder for the changes built during the current call
|
||||
*/
|
||||
public static Set<? extends GradleProjectStructureChange> buildLocalChanges(@NotNull Module module) {
|
||||
Set<GradleProjectStructureChange> result = new HashSet<GradleProjectStructureChange>();
|
||||
result.add(new GradleModulePresenceChange(null, module));
|
||||
public static void buildLocalChanges(@NotNull Module module, @NotNull Set<GradleProjectStructureChange> currentChanges) {
|
||||
currentChanges.add(new GradleModulePresenceChange(null, module));
|
||||
// TODO den process module sub-entities here (content roots and dependencies).
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analogues to {@link #buildLocalChanges} but targets intellij entity.
|
||||
*
|
||||
* @param libraryDependency target intellij-local library dependency that doesn't present at the gradle side
|
||||
* @return collection of intellij-local changes for the given entity and its interested sub-entities
|
||||
* @param currentChanges holder for the changes built during the current call
|
||||
*/
|
||||
public static Set<? extends GradleProjectStructureChange> buildLocalChanges(@NotNull LibraryOrderEntry libraryDependency) {
|
||||
return Collections.singleton(new GradleLibraryDependencyPresenceChange(null, libraryDependency));
|
||||
public static void buildLocalChanges(@NotNull LibraryOrderEntry libraryDependency,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
currentChanges.add(new GradleLibraryDependencyPresenceChange(null, libraryDependency));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs argument type-based dispatch and delegates to one of strongly typed <code>'buildLocalChanges()'</code> methods.
|
||||
*
|
||||
* @param entity target intellij-local entity that doesn't present at the gradle side
|
||||
* @return collection of intellij-local changes for the given entity and its interested sub-entities
|
||||
* @param entity target intellij-local entity that doesn't present at the gradle side
|
||||
* @param currentChanges holder for the changes built during the current call
|
||||
*/
|
||||
@NotNull
|
||||
public static Set<? extends GradleProjectStructureChange> buildLocalChanges(@NotNull Object entity) {
|
||||
public static void buildLocalChanges(@NotNull Object entity,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
if (entity instanceof GradleEntity) {
|
||||
return buildLocalChanges((GradleEntity)entity);
|
||||
buildLocalChanges((GradleEntity)entity, currentChanges);
|
||||
}
|
||||
else if (entity instanceof Module) {
|
||||
return buildLocalChanges((Module)entity);
|
||||
buildLocalChanges((Module)entity, currentChanges);
|
||||
}
|
||||
else if (entity instanceof LibraryOrderEntry) {
|
||||
return buildLocalChanges((LibraryOrderEntry)entity);
|
||||
buildLocalChanges((LibraryOrderEntry)entity, currentChanges);
|
||||
}
|
||||
else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates given entities into the single collection and returns it.
|
||||
* <p/>
|
||||
* The main idea behind this method is that most of the time we don't expect changes at all, hence, corresponding changes calculators
|
||||
* can use {@link Collections#emptySet()}. However, if some sub-nodes do have changes, attempt
|
||||
* to {@link Collection#addAll(Collection) merge} them within the empty set mentioned above would cause an exception.
|
||||
* <p/>
|
||||
* That's why we provide dedicated method for creating new collection as a merge result.
|
||||
*
|
||||
* @param collections collections to merge
|
||||
* @return merge result
|
||||
*/
|
||||
@NotNull
|
||||
public static Set<GradleProjectStructureChange> concatenate(Collection<? extends GradleProjectStructureChange>... collections) {
|
||||
Set<GradleProjectStructureChange> result = null;
|
||||
for (Collection<? extends GradleProjectStructureChange> collection : collections) {
|
||||
if (result == null) {
|
||||
result = new HashSet<GradleProjectStructureChange>();
|
||||
}
|
||||
result.addAll(collection);
|
||||
}
|
||||
return result == null ? Collections.<GradleProjectStructureChange>emptySet() : result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,39 +118,34 @@ public class GradleDiffUtil {
|
||||
* @param gradleEntities entities available at the gradle side
|
||||
* @param intellijEntities entities available at the intellij side
|
||||
* @param knownChanges collection that contains known changes about the entities
|
||||
* @param currentChanges holder for the changes discovered during the current call
|
||||
* @param <I> target intellij entity type
|
||||
* @param <G> target gradle entity type
|
||||
* @return set of changes between the given entity collections
|
||||
*/
|
||||
@NotNull
|
||||
public static <I, G extends GradleEntity> Set<GradleProjectStructureChange> calculate(
|
||||
public static <I, G extends GradleEntity> void calculate(
|
||||
@NotNull GradleStructureChangesCalculator<G, I> calculator,
|
||||
@NotNull Iterable<? extends G> gradleEntities,
|
||||
@NotNull Iterable<? extends I> intellijEntities,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
Set<GradleProjectStructureChange> result = Collections.emptySet();
|
||||
Map<Object, I> intellijEntitiesByKeys = new HashMap<Object, I>();
|
||||
for (I entity : intellijEntities) {
|
||||
final I previous = intellijEntitiesByKeys.put(calculator.getIntellijKey(entity, knownChanges), entity);
|
||||
final I previous = intellijEntitiesByKeys.put(calculator.getIntellijKey(entity), entity);
|
||||
assert previous == null;
|
||||
}
|
||||
for (G gradleEntity: gradleEntities) {
|
||||
I intellijEntity = intellijEntitiesByKeys.remove(calculator.getGradleKey(gradleEntity, knownChanges));
|
||||
Set<GradleProjectStructureChange> changesToMerge;
|
||||
if (intellijEntity == null) {
|
||||
changesToMerge = buildLocalChanges(gradleEntity);
|
||||
buildLocalChanges(gradleEntity, currentChanges);
|
||||
}
|
||||
else {
|
||||
changesToMerge = calculator.calculate(gradleEntity, intellijEntity, knownChanges);
|
||||
calculator.calculate(gradleEntity, intellijEntity, knownChanges, currentChanges);
|
||||
}
|
||||
result = concatenate(result, changesToMerge);
|
||||
}
|
||||
|
||||
for (I entity : intellijEntitiesByKeys.values()) {
|
||||
result = concatenate(result, buildLocalChanges(entity));
|
||||
buildLocalChanges(entity, currentChanges);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -4,7 +4,6 @@ import com.intellij.openapi.roots.LibraryOrderEntry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.model.GradleLibraryDependency;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -14,20 +13,19 @@ import java.util.Set;
|
||||
public class GradleLibraryDependencyStructureChangesCalculator
|
||||
implements GradleStructureChangesCalculator<GradleLibraryDependency, LibraryOrderEntry>
|
||||
{
|
||||
@NotNull
|
||||
|
||||
@Override
|
||||
public Set<GradleProjectStructureChange> calculate(@NotNull GradleLibraryDependency gradleEntity,
|
||||
@NotNull LibraryOrderEntry intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
public void calculate(@NotNull GradleLibraryDependency gradleEntity,
|
||||
@NotNull LibraryOrderEntry intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
// TODO den implement
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object getIntellijKey(@NotNull LibraryOrderEntry entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
|
||||
// TODO den consider the known changes
|
||||
public Object getIntellijKey(@NotNull LibraryOrderEntry entity) {
|
||||
final String result = entity.getLibraryName();
|
||||
return result == null ? "" : result;
|
||||
}
|
||||
|
||||
+26
-22
@@ -34,24 +34,30 @@ import java.util.Set;
|
||||
*/
|
||||
public class GradleModuleStructureChangesCalculator implements GradleStructureChangesCalculator<GradleModule, Module> {
|
||||
|
||||
private final GradleLibraryDependencyStructureChangesCalculator myLibraryDependencyCalculator
|
||||
= new GradleLibraryDependencyStructureChangesCalculator();
|
||||
|
||||
@NotNull
|
||||
private final GradleLibraryDependencyStructureChangesCalculator myLibraryDependencyCalculator;
|
||||
private final GradleProjectStructureHelper myStructureHelper;
|
||||
|
||||
public GradleModuleStructureChangesCalculator(@NotNull GradleLibraryDependencyStructureChangesCalculator libraryDependencyCalculator,
|
||||
@NotNull GradleProjectStructureHelper structureHelper)
|
||||
{
|
||||
myLibraryDependencyCalculator = libraryDependencyCalculator;
|
||||
myStructureHelper = structureHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<GradleProjectStructureChange> calculate(@NotNull GradleModule gradleEntity,
|
||||
@NotNull Module intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
public void calculate(@NotNull GradleModule gradleEntity,
|
||||
@NotNull Module intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
//TODO den process module-local settings
|
||||
//TODO den process content roots
|
||||
return checkDependencies(gradleEntity, intellijEntity, knownChanges);
|
||||
//TODO den process content roots
|
||||
checkDependencies(gradleEntity, intellijEntity, knownChanges, currentChanges);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object getIntellijKey(@NotNull Module entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
|
||||
// TODO den consider the known changes
|
||||
public Object getIntellijKey(@NotNull Module entity) {
|
||||
return entity.getName();
|
||||
}
|
||||
|
||||
@@ -62,9 +68,10 @@ public class GradleModuleStructureChangesCalculator implements GradleStructureCh
|
||||
return entity.getName();
|
||||
}
|
||||
|
||||
private Set<GradleProjectStructureChange> checkDependencies(@NotNull GradleModule gradleModule,
|
||||
@NotNull Module intellijModule,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
private void checkDependencies(@NotNull GradleModule gradleModule,
|
||||
@NotNull Module intellijModule,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
// Prepare intellij part.
|
||||
final List<ModuleOrderEntry> intellijModuleDependencies = new ArrayList<ModuleOrderEntry>();
|
||||
@@ -82,11 +89,10 @@ public class GradleModuleStructureChangesCalculator implements GradleStructureCh
|
||||
return libraryOrderEntry;
|
||||
}
|
||||
};
|
||||
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(intellijModule);
|
||||
for (OrderEntry orderEntry : moduleRootManager.getOrderEntries()) {
|
||||
for (OrderEntry orderEntry : myStructureHelper.getOrderEntries(intellijModule)) {
|
||||
orderEntry.accept(policy, null);
|
||||
}
|
||||
|
||||
|
||||
// Prepare gradle part.
|
||||
final List<GradleModuleDependency> gradleModuleDependencies = new ArrayList<GradleModuleDependency>();
|
||||
final List<GradleLibraryDependency> gradleLibraryDependencies = new ArrayList<GradleLibraryDependency>();
|
||||
@@ -104,12 +110,10 @@ public class GradleModuleStructureChangesCalculator implements GradleStructureCh
|
||||
for (GradleDependency dependency : gradleModule.getDependencies()) {
|
||||
dependency.invite(visitor);
|
||||
}
|
||||
|
||||
|
||||
// Calculate changes.
|
||||
// TODO den process module dependencies here as well.
|
||||
final Set<GradleProjectStructureChange> libraryChanges
|
||||
= GradleDiffUtil.calculate(myLibraryDependencyCalculator, gradleLibraryDependencies, intellijLibraryDependencies, knownChanges);
|
||||
return libraryChanges;
|
||||
|
||||
GradleDiffUtil.calculate(myLibraryDependencyCalculator, gradleLibraryDependencies, intellijLibraryDependencies,
|
||||
knownChanges, currentChanges);
|
||||
}
|
||||
}
|
||||
|
||||
+33
-43
@@ -1,21 +1,15 @@
|
||||
package org.jetbrains.plugins.gradle.diff;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.model.GradleModule;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.jetbrains.plugins.gradle.diff.GradleDiffUtil.concatenate;
|
||||
|
||||
/**
|
||||
* Encapsulates functionality of calculating changes between Gradle and IntelliJ IDEA project hierarchies.
|
||||
* <p/>
|
||||
@@ -26,25 +20,31 @@ import static org.jetbrains.plugins.gradle.diff.GradleDiffUtil.concatenate;
|
||||
*/
|
||||
public class GradleProjectStructureChangesCalculator implements GradleStructureChangesCalculator<GradleProject, Project> {
|
||||
|
||||
private final GradleModuleStructureChangesCalculator myModuleChangesCalculator = new GradleModuleStructureChangesCalculator();
|
||||
private final GradleModuleStructureChangesCalculator myModuleChangesCalculator;
|
||||
private final GradleProjectStructureHelper myStructureHelper;
|
||||
|
||||
public GradleProjectStructureChangesCalculator(@NotNull GradleModuleStructureChangesCalculator moduleCalculator,
|
||||
@NotNull GradleProjectStructureHelper structureHelper) {
|
||||
myModuleChangesCalculator = moduleCalculator;
|
||||
myStructureHelper = structureHelper;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<GradleProjectStructureChange> calculate(@NotNull GradleProject gradleEntity,
|
||||
@NotNull Project intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
public void calculate(@NotNull GradleProject gradleEntity,
|
||||
@NotNull Project intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
final Set<GradleProjectStructureChange> result = calculateProjectChanges(gradleEntity, intellijEntity, knownChanges);
|
||||
calculateProjectChanges(gradleEntity, intellijEntity, currentChanges);
|
||||
|
||||
final Set<? extends GradleModule> gradleSubEntities = gradleEntity.getModules();
|
||||
final List<Module> intellijSubEntities = asList(ModuleManager.getInstance(intellijEntity).getModules());
|
||||
return concatenate(result, GradleDiffUtil.calculate(myModuleChangesCalculator, gradleSubEntities, intellijSubEntities, knownChanges));
|
||||
final Collection<Module> intellijSubEntities = myStructureHelper.getModules(intellijEntity);
|
||||
GradleDiffUtil.calculate(myModuleChangesCalculator, gradleSubEntities, intellijSubEntities, knownChanges, currentChanges);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object getIntellijKey(@NotNull Project entity, @NotNull Set<GradleProjectStructureChange> knownChanges) {
|
||||
// TODO den consider the known changes
|
||||
public Object getIntellijKey(@NotNull Project entity) {
|
||||
return entity.getName();
|
||||
}
|
||||
|
||||
@@ -55,43 +55,33 @@ public class GradleProjectStructureChangesCalculator implements GradleStructureC
|
||||
return entity.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<GradleProjectStructureChange> calculateProjectChanges(@NotNull GradleProject gradleProject,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
private void calculateProjectChanges(@NotNull GradleProject gradleProject,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
final Set<GradleProjectStructureChange> nameChanges = checkName(gradleProject, intellijProject, knownChanges);
|
||||
final Set<GradleProjectStructureChange> levelChanges = checkLanguageLevel(gradleProject, intellijProject, knownChanges);
|
||||
return concatenate(nameChanges, levelChanges);
|
||||
checkName(gradleProject, intellijProject, currentChanges);
|
||||
checkLanguageLevel(gradleProject, intellijProject, currentChanges);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<GradleProjectStructureChange> checkName(@NotNull GradleProject gradleProject,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
private static void checkName(@NotNull GradleProject gradleProject,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
String gradleName = gradleProject.getName();
|
||||
String intellijName = intellijProject.getName();
|
||||
if (gradleName.equals(intellijName)) {
|
||||
return Collections.emptySet();
|
||||
if (!gradleName.equals(intellijName)) {
|
||||
currentChanges.add(new GradleRenameChange(GradleRenameChange.Entity.PROJECT, gradleName, intellijName));
|
||||
}
|
||||
final GradleRenameChange change = new GradleRenameChange(GradleRenameChange.Entity.PROJECT, gradleName, intellijName);
|
||||
return knownChanges.contains(change) ? Collections.<GradleProjectStructureChange>emptySet()
|
||||
: Collections.<GradleProjectStructureChange>singleton(change);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<GradleProjectStructureChange> checkLanguageLevel(@NotNull GradleProject gradleProject,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges)
|
||||
private void checkLanguageLevel(@NotNull GradleProject gradleProject,
|
||||
@NotNull Project intellijProject,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
LanguageLevel gradleLevel = gradleProject.getLanguageLevel();
|
||||
LanguageLevel intellijLevel = LanguageLevelProjectExtension.getInstance(intellijProject).getLanguageLevel();
|
||||
if (gradleLevel == intellijLevel) {
|
||||
return Collections.emptySet();
|
||||
LanguageLevel intellijLevel = myStructureHelper.getLanguageLevel(intellijProject);
|
||||
if (gradleLevel != intellijLevel) {
|
||||
currentChanges.add(new GradleLanguageLevelChange(gradleLevel, intellijLevel));
|
||||
}
|
||||
final GradleLanguageLevelChange change = new GradleLanguageLevelChange(gradleLevel, intellijLevel);
|
||||
return knownChanges.contains(change) ? Collections.<GradleProjectStructureChange>emptySet()
|
||||
: Collections.<GradleProjectStructureChange>singleton(change);
|
||||
}
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package org.jetbrains.plugins.gradle.diff;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* IntelliJ code provides a lot of statical bindings to the interested pieces of data. For example we need to execute code
|
||||
* like below to get list of modules for the target project:
|
||||
* <pre>
|
||||
* ModuleManager.getInstance(project).getModules()
|
||||
* </pre>
|
||||
* That means that it's not possible to test target classes in isolation if corresponding infrastructure is not set up.
|
||||
* However, we don't want to set it up if we execute a simple standalone test.
|
||||
* <p/>
|
||||
* This interface is intended to encapsulate access to the underlying project infrastructure.
|
||||
* <p/>
|
||||
* Implementations of this interface are expected to be thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/26/12 11:32 AM
|
||||
*/
|
||||
public interface GradleProjectStructureHelper {
|
||||
|
||||
@NotNull
|
||||
LanguageLevel getLanguageLevel(@NotNull Project project);
|
||||
|
||||
@NotNull
|
||||
Collection<Module> getModules(@NotNull Project project);
|
||||
|
||||
@NotNull
|
||||
Collection<OrderEntry> getOrderEntries(@NotNull Module module);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.plugins.gradle.diff;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/26/12 11:54 AM
|
||||
*/
|
||||
public class GradleProjectStructureHelperImpl implements GradleProjectStructureHelper {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LanguageLevel getLanguageLevel(@NotNull Project project) {
|
||||
return LanguageLevelProjectExtension.getInstance(project).getLanguageLevel();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Module> getModules(@NotNull Project project) {
|
||||
return Arrays.asList(ModuleManager.getInstance(project).getModules());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<OrderEntry> getOrderEntries(@NotNull Module module) {
|
||||
return Arrays.asList(ModuleRootManager.getInstance(module).getOrderEntries());
|
||||
}
|
||||
}
|
||||
+52
-9
@@ -18,17 +18,60 @@ import java.util.Set;
|
||||
*/
|
||||
public interface GradleStructureChangesCalculator<G extends GradleEntity, I> {
|
||||
|
||||
// TODO den add doc
|
||||
@NotNull
|
||||
Set<GradleProjectStructureChange> calculate(@NotNull G gradleEntity,
|
||||
@NotNull I intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges);
|
||||
/**
|
||||
* Calculates changes between the given entities.
|
||||
*
|
||||
* @param gradleEntity target gradle entity
|
||||
* @param intellijEntity target intellij entity
|
||||
* @param knownChanges changes between the gradle and intellij project structure that has been known up until now
|
||||
* @param currentChanges holder for the changes between the given entities discovered by the current call. Note that
|
||||
* it must contain the change objects that have been known (contained at the <code>'knownChanges'</code>)
|
||||
* but are still in place
|
||||
*/
|
||||
void calculate(@NotNull G gradleEntity,
|
||||
@NotNull I intellijEntity,
|
||||
@NotNull Set<GradleProjectStructureChange> knownChanges,
|
||||
@NotNull Set<GradleProjectStructureChange> currentChanges);
|
||||
|
||||
// TODO den add doc
|
||||
/**
|
||||
* There are three possible situations when we compare a set of gradle entities with a set of intellij entities:
|
||||
* <pre>
|
||||
* <ul>
|
||||
* <li>particular entity presents only at the gradle side;</li>
|
||||
* <li>particular entity presents only at the intellij side;</li>
|
||||
* <li>particular gradle entity is matched to particular intellij entity (they may have difference in their settings though);</li>
|
||||
* </ul>
|
||||
* </pre>
|
||||
* <p/>
|
||||
* The general idea is to map evey item at the given sets of gradle and intellij entities to particular key (both gradle and
|
||||
* intellij keys are expected to belong to the same class) and then compare them. Matched keys shows that corresponding
|
||||
* entities should be {@link #calculate(GradleEntity, Object, Set) compared to each other}; non-matched indicate that corresponding
|
||||
* entities are gradle- or intellij-local.
|
||||
* <p/>
|
||||
* This method allows to match intellij entity to the target key.
|
||||
*
|
||||
* @param entity intellij entity to match
|
||||
* @return key for the given entity
|
||||
* @see #getGradleKey(GradleEntity, Set)
|
||||
*/
|
||||
@NotNull
|
||||
Object getIntellijKey(@NotNull I entity, @NotNull Set<GradleProjectStructureChange> knownChanges);
|
||||
|
||||
// TODO den add doc
|
||||
Object getIntellijKey(@NotNull I entity);
|
||||
|
||||
/**
|
||||
* Serves the same purpose as {@link #getIntellijKey(Object)} but targets gradle entities.
|
||||
* <p/>
|
||||
* There is a possible case that two corresponding gradle and intellij entities differ from each other by the setting that
|
||||
* affects the resulting key (e.g. we may use module name as a key for 'module' entities and intellij module name differs from
|
||||
* the name of the corresponding gradle module). We need to match only in one direction then (e.g. consider a situation when
|
||||
* particular module is named differently at gradle and intellij. We shouldn't consider that change during both
|
||||
* {@code intellij-entity -> key} and {@code gradle-entity -> key} mappings because that would produce two different keys).
|
||||
* So, we take into consideration the known changes only during {@code gradle-entity -> key} processing.
|
||||
*
|
||||
* @param entity target gradle entity that should be mapped to a key
|
||||
* @param knownChanges known changes between the gradle and intellij structures
|
||||
* @return key for the given entity
|
||||
* @see #getIntellijKey(Object)
|
||||
*/
|
||||
@NotNull
|
||||
Object getGradleKey(@NotNull G entity, @NotNull Set<GradleProjectStructureChange> knownChanges);
|
||||
}
|
||||
|
||||
+4
-2
@@ -18,7 +18,9 @@ public interface GradleProjectStructureChangeListener {
|
||||
/**
|
||||
* Notifies current listener on the newly discovered changes between the gradle and intellij project models.
|
||||
*
|
||||
* @param changes newly discovered changes between the gradle and intellij project models.
|
||||
* @param oldChanges changes between the gradle and intellij project models that had been known prior to the current update
|
||||
* @param currentChanges the most up-to-date changes between the gradle and intellij project models
|
||||
*/
|
||||
void onChanges(@NotNull Collection<GradleProjectStructureChange> changes);
|
||||
void onChanges(@NotNull Collection<GradleProjectStructureChange> oldChanges,
|
||||
@NotNull Collection<GradleProjectStructureChange> currentChanges);
|
||||
}
|
||||
|
||||
+20
-10
@@ -2,15 +2,15 @@ package org.jetbrains.plugins.gradle.sync;
|
||||
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.containers.ConcurrentHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
|
||||
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangesCalculator;
|
||||
import org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator;
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* // TODO den add doc
|
||||
@@ -23,11 +23,14 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
public class GradleProjectStructureChangesModel extends AbstractProjectComponent {
|
||||
|
||||
private final Set<GradleProjectStructureChangeListener> myListeners = new CopyOnWriteArraySet<GradleProjectStructureChangeListener>();
|
||||
private final Set<GradleProjectStructureChange> myChanges = new ConcurrentHashSet<GradleProjectStructureChange>();
|
||||
private final AtomicReference<Set<GradleProjectStructureChange>> myChanges
|
||||
= new AtomicReference<Set<GradleProjectStructureChange>>(new HashSet<GradleProjectStructureChange>());
|
||||
|
||||
private final GradleProjectStructureChangesCalculator myChangesCalculator;
|
||||
private final GradleStructureChangesCalculator<GradleProject, Project> myChangesCalculator;
|
||||
|
||||
public GradleProjectStructureChangesModel(@NotNull Project project, @NotNull GradleProjectStructureChangesCalculator changesCalculator) {
|
||||
public GradleProjectStructureChangesModel(@NotNull Project project,
|
||||
@NotNull GradleStructureChangesCalculator<GradleProject, Project> changesCalculator)
|
||||
{
|
||||
super(project);
|
||||
myChangesCalculator = changesCalculator;
|
||||
}
|
||||
@@ -44,15 +47,22 @@ public class GradleProjectStructureChangesModel extends AbstractProjectComponent
|
||||
* </li>
|
||||
* <li>{@link #addListener(GradleProjectStructureChangeListener) Registered listeners} are notified if any new change is detected;</li>
|
||||
* </ol>
|
||||
* <p/>
|
||||
* <b>Note:</b> it's very important that the listeners are notified <b>after</b> the actual state change, i.e. {@link #getChanges()}
|
||||
* during the update returns up-to-date data.
|
||||
*
|
||||
* @param gradleProject gradle project to sync with
|
||||
*/
|
||||
public void update(@NotNull GradleProject gradleProject) {
|
||||
Set<GradleProjectStructureChange> knownChanges = new HashSet<GradleProjectStructureChange>(myChanges);
|
||||
final Set<GradleProjectStructureChange> newChanges = myChangesCalculator.calculate(gradleProject, myProject, knownChanges);
|
||||
myChanges.addAll(newChanges);
|
||||
Set<GradleProjectStructureChange> knownChanges = new HashSet<GradleProjectStructureChange>(myChanges.get());
|
||||
Set<GradleProjectStructureChange> currentChanges = new HashSet<GradleProjectStructureChange>();
|
||||
myChangesCalculator.calculate(gradleProject, myProject, knownChanges, currentChanges);
|
||||
if (currentChanges.equals(knownChanges)) {
|
||||
return;
|
||||
}
|
||||
myChanges.set(currentChanges);
|
||||
for (GradleProjectStructureChangeListener listener : myListeners) {
|
||||
listener.onChanges(newChanges);
|
||||
listener.onChanges(knownChanges, currentChanges);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +82,6 @@ public class GradleProjectStructureChangesModel extends AbstractProjectComponent
|
||||
*/
|
||||
@NotNull
|
||||
public Set<GradleProjectStructureChange> getChanges() {
|
||||
return myChanges;
|
||||
return myChanges.get();
|
||||
}
|
||||
}
|
||||
|
||||
+92
-2
@@ -8,6 +8,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.RootPolicy;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.HashMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -25,6 +26,8 @@ import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.MutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -51,6 +54,9 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
|
||||
*/
|
||||
private final Map<String, DefaultMutableTreeNode> myModuleDependencies = new HashMap<String, DefaultMutableTreeNode>();
|
||||
private final Map<String, DefaultMutableTreeNode> myModules = new HashMap<String, DefaultMutableTreeNode>();
|
||||
|
||||
private final TreeNode[] myNodeHolder = new TreeNode[1];
|
||||
private final int[] myIndexHolder = new int[1];
|
||||
|
||||
private final GradleProjectStructureChangesModel myChangesModel;
|
||||
|
||||
@@ -62,11 +68,15 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
|
||||
myChangesModel = model;
|
||||
myChangesModel.addListener(new GradleProjectStructureChangeListener() {
|
||||
@Override
|
||||
public void onChanges(@NotNull final Collection<GradleProjectStructureChange> changes) {
|
||||
public void onChanges(@NotNull final Collection<GradleProjectStructureChange> oldChanges,
|
||||
@NotNull final Collection<GradleProjectStructureChange> currentChanges)
|
||||
{
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateTree(changes);
|
||||
updateTree(currentChanges);
|
||||
processObsoleteChanges(ContainerUtil.subtract(oldChanges, currentChanges));
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -84,6 +94,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
|
||||
constraints.fill = GridBagConstraints.BOTH;
|
||||
constraints.weightx = constraints.weighty = 1;
|
||||
myContent.add(tree, constraints);
|
||||
myContent.setBackground(tree.getBackground());
|
||||
return treeModel;
|
||||
}
|
||||
|
||||
@@ -237,4 +248,83 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the tree state considering that the given changes are obsolete.
|
||||
* <p/>
|
||||
* Example:
|
||||
* <pre>
|
||||
* <ol>
|
||||
* <li>There is a particular intellij-local library (change from the gradle project structure);</li>
|
||||
* <li>Corresponding node is shown at the current UI;</li>
|
||||
* <li>The library is removed, i.e. corresponding change has become obsolete;</li>
|
||||
* <li>This method is notified within the obsolete change and is expected to remove the corresponding node;</li>
|
||||
* </ol>
|
||||
* </pre>
|
||||
*/
|
||||
private void processObsoleteChanges(Collection<GradleProjectStructureChange> changes) {
|
||||
for (GradleProjectStructureChange change : changes) {
|
||||
change.invite(new GradleProjectStructureChangeVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull GradleRenameChange change) {
|
||||
// TODO den implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull GradleProjectStructureChange change) {
|
||||
// TODO den implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull GradleModulePresenceChange change) {
|
||||
// TODO den implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull GradleLibraryDependencyPresenceChange change) {
|
||||
// We need to remove the corresponding node then.
|
||||
String moduleName;
|
||||
Object library;
|
||||
final GradleLibraryDependency gradleEntity = change.getGradleEntity();
|
||||
final LibraryOrderEntry intellijEntity = change.getIntellijEntity();
|
||||
assert gradleEntity != null || intellijEntity != null;
|
||||
if (gradleEntity == null) {
|
||||
moduleName = intellijEntity.getOwnerModule().getName();
|
||||
library = intellijEntity;
|
||||
}
|
||||
else {
|
||||
moduleName = gradleEntity.getOwnerModule().getName();
|
||||
library = gradleEntity;
|
||||
}
|
||||
final DefaultMutableTreeNode holder = myModuleDependencies.get(moduleName);
|
||||
if (holder == null) {
|
||||
return;
|
||||
}
|
||||
for (DefaultMutableTreeNode node = holder.getFirstLeaf(); node != null; node = node.getNextSibling()) {
|
||||
GradleProjectStructureNodeDescriptor<?> descriptor = (GradleProjectStructureNodeDescriptor<?>)node.getUserObject();
|
||||
if (descriptor.getElement().equals(library)) {
|
||||
removeNode(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNode(@NotNull TreeNode node) {
|
||||
final MutableTreeNode parent = (MutableTreeNode)node.getParent();
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
int i = parent.getIndex(node);
|
||||
if (i <= 0) {
|
||||
assert false : node;
|
||||
return;
|
||||
}
|
||||
parent.remove(i);
|
||||
myIndexHolder[0] = i;
|
||||
myNodeHolder[0] = node;
|
||||
myTreeModel.nodesWereRemoved(parent, myIndexHolder, myNodeHolder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,12 @@ public class GradleResolveProjectTask extends AbstractGradleTask {
|
||||
return;
|
||||
}
|
||||
final GradleProjectStructureChangesModel model = myIntellijProject.getComponent(GradleProjectStructureChangesModel.class);
|
||||
model.update(project);
|
||||
if (model != null) {
|
||||
// This task may be called during the 'import from gradle' processing, hence, no project-level IoC is up.
|
||||
// Model update is necessary for the correct tool window project structure diff showing but we don't have
|
||||
// gradle tool window on this stage.
|
||||
model.update(project);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package org.jetbrains.plugins.gradle.sync;
|
||||
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.plugins.gradle.testutil.ChangeBuilder
|
||||
import org.jetbrains.plugins.gradle.testutil.GradleProjectBuilder
|
||||
import org.jetbrains.plugins.gradle.testutil.IntellijProjectBuilder
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.picocontainer.defaults.DefaultPicoContainer
|
||||
import org.jetbrains.plugins.gradle.diff.*
|
||||
import static org.junit.Assert.assertEquals
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 01/25/2012
|
||||
*/
|
||||
public class GradleProjectStructureChangesModelTest {
|
||||
|
||||
private GradleProjectStructureChangesModel myModel;
|
||||
def gradle;
|
||||
def intellij;
|
||||
def changes;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
gradle = new GradleProjectBuilder()
|
||||
intellij = new IntellijProjectBuilder()
|
||||
changes = new ChangeBuilder()
|
||||
def container = new DefaultPicoContainer()
|
||||
container.registerComponentInstance(Project, intellij.project)
|
||||
container.registerComponentInstance(GradleProjectStructureHelper, intellij.projectStructureHelper as GradleProjectStructureHelper)
|
||||
container.registerComponentImplementation(GradleProjectStructureChangesModel)
|
||||
container.registerComponentImplementation(GradleStructureChangesCalculator, GradleProjectStructureChangesCalculator)
|
||||
container.registerComponentImplementation(GradleModuleStructureChangesCalculator)
|
||||
container.registerComponentImplementation(GradleLibraryDependencyStructureChangesCalculator)
|
||||
|
||||
myModel = container.getComponentInstance(GradleProjectStructureChangesModel.class) as GradleProjectStructureChangesModel
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeGradleLocalToIntellij() {
|
||||
gradle {
|
||||
module {
|
||||
dependencies {
|
||||
lib(name: "lib1")
|
||||
lib(name: "lib2")
|
||||
} } }
|
||||
|
||||
intellij {
|
||||
module {
|
||||
dependencies {
|
||||
lib(name: "lib1")
|
||||
} } }
|
||||
|
||||
myModel.update(gradle.project)
|
||||
checkChanges {
|
||||
presence {
|
||||
lib(gradle: gradle.modules.dependencies.flatten().findAll { it.name == "lib2" })
|
||||
}
|
||||
}
|
||||
|
||||
gradle {
|
||||
module {
|
||||
dependencies {
|
||||
lib(name: "lib1")
|
||||
} } }
|
||||
myModel.update(gradle.project)
|
||||
assertEquals([].toSet(), myModel.changes)
|
||||
}
|
||||
|
||||
private def checkChanges(c) {
|
||||
c.delegate = changes
|
||||
assertEquals(c(), myModel.changes)
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package org.jetbrains.plugins.gradle.testutil
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/25/12 4:06 PM
|
||||
*/
|
||||
public abstract class AbstractProjectBuilder extends BuilderSupport {
|
||||
|
||||
private static final def SAME_TOKEN = "same"
|
||||
private static int COUNTER
|
||||
|
||||
def project
|
||||
def modules = []
|
||||
def libraries = [:].withDefault { createLibrary(it.name?: same, it.paths?: [:]) }
|
||||
def dependencies = [:].withDefault {[]}
|
||||
|
||||
@Override
|
||||
protected void setParent(Object parent, Object child) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name) {
|
||||
switch (name) {
|
||||
case "call": return createNode("project", [name: same])
|
||||
case "module": return createNode(name, [name: same])
|
||||
case "dependencies": return getCurrent() // Assuming that 'current' is a module object
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name, Object value) {
|
||||
return null
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name, Map attributes) {
|
||||
switch (name) {
|
||||
case "project":
|
||||
reset()
|
||||
return project = createProject(attributes.name?: same, attributes.langLevel?: LanguageLevel.JDK_1_6)
|
||||
case "module": def module = createModule(attributes.name?: same); modules << module; return module
|
||||
case "lib":
|
||||
def module = getCurrent()
|
||||
def dep = createLibraryDependency(module, libraries[attributes])
|
||||
dependencies[module] << dep
|
||||
return dep
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name, Map attributes, Object value) {
|
||||
return null
|
||||
}
|
||||
|
||||
protected abstract def createProject(String name, LanguageLevel languageLevel)
|
||||
protected abstract def createModule(String name)
|
||||
protected abstract def createLibrary(String name, Map paths)
|
||||
protected abstract def createLibraryDependency(module, library)
|
||||
|
||||
protected String getUnique() { "./${COUNTER++}" }
|
||||
protected String getSame() { SAME_TOKEN }
|
||||
|
||||
private def reset() {
|
||||
[modules, dependencies, libraries]*.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.jetbrains.plugins.gradle.testutil;
|
||||
|
||||
|
||||
import org.jetbrains.plugins.gradle.diff.GradleLibraryDependencyPresenceChange
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/26/12 3:25 PM
|
||||
*/
|
||||
public class ChangeBuilder extends BuilderSupport {
|
||||
|
||||
def changes = []
|
||||
|
||||
@Override
|
||||
protected void setParent(Object parent, Object child) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name) {
|
||||
if (current == null) {
|
||||
changes = []
|
||||
}
|
||||
changes
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name, Object value) { changes }
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name, Map attributes) {
|
||||
switch (name) {
|
||||
case "presence": return changes
|
||||
case "lib":
|
||||
changes.addAll attributes.gradle.collect { new GradleLibraryDependencyPresenceChange(it, null)}
|
||||
changes.addAll attributes.intellij.collect { new GradleLibraryDependencyPresenceChange(null, it)}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createNode(Object name, Map attributes, Object value) { changes }
|
||||
|
||||
@Override
|
||||
protected Object postNodeCompletion(Object parent, Object node) {
|
||||
parent == null ? changes.toSet() : node
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package org.jetbrains.plugins.gradle.testutil
|
||||
|
||||
import org.jetbrains.plugins.gradle.model.GradleProject
|
||||
import org.jetbrains.plugins.gradle.model.GradleModule
|
||||
import org.jetbrains.plugins.gradle.model.GradleLibraryDependency
|
||||
import org.jetbrains.plugins.gradle.model.GradleLibrary
|
||||
import org.jetbrains.plugins.gradle.model.LibraryPathType
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/25/12 1:29 PM
|
||||
*/
|
||||
class GradleProjectBuilder extends AbstractProjectBuilder {
|
||||
|
||||
@Override
|
||||
protected createProject(String name, LanguageLevel languageLevel) {
|
||||
def result = new GradleProject(same, same)
|
||||
result.name = name
|
||||
result.languageLevel = languageLevel
|
||||
result
|
||||
}
|
||||
|
||||
@Override
|
||||
protected createModule(String name) {
|
||||
def result = new GradleModule(name, unique)
|
||||
project.addModule(result)
|
||||
result
|
||||
}
|
||||
|
||||
@Override
|
||||
protected createLibrary(String name, Map paths) {
|
||||
def result = new GradleLibrary(name)
|
||||
(paths.bin?: [same]).each { result.addPath(LibraryPathType.BINARY, it) }
|
||||
(paths.src?: [same]).each { result.addPath(LibraryPathType.SOURCE, it) }
|
||||
(paths.doc?: [same]).each { result.addPath(LibraryPathType.DOC, it) }
|
||||
result
|
||||
}
|
||||
|
||||
@Override
|
||||
protected createLibraryDependency(module, library) {
|
||||
def result = new GradleLibraryDependency(module, library)
|
||||
module.addDependency(result)
|
||||
result
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package org.jetbrains.plugins.gradle.testutil
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.RootPolicy
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||
import groovy.mock.interceptor.StubFor
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
* @since 1/25/12 3:09 PM
|
||||
*/
|
||||
class IntellijProjectBuilder extends AbstractProjectBuilder {
|
||||
|
||||
def projectStub = [:]
|
||||
def project = projectStub as Project
|
||||
def projectStructureHelper = [
|
||||
getModules: { modules },
|
||||
getOrderEntries: { dependencies[it] }
|
||||
]
|
||||
|
||||
@Override
|
||||
protected createProject(String name, LanguageLevel languageLevel) {
|
||||
projectStub.getName = { name }
|
||||
projectStructureHelper.getLanguageLevel = { languageLevel }
|
||||
project
|
||||
}
|
||||
|
||||
@Override
|
||||
protected createModule(String name) {
|
||||
[ getName: { name } ] as Module
|
||||
}
|
||||
|
||||
@Override
|
||||
protected createLibrary(String name, Map paths) {
|
||||
[ getName: { name } ] as Library
|
||||
}
|
||||
|
||||
@Override
|
||||
protected createLibraryDependency(module, library) {
|
||||
def stub = [:]
|
||||
def result = stub as LibraryOrderEntry
|
||||
stub.accept = { policy, defaultValue -> policy.visitLibraryOrderEntry(result, defaultValue) }
|
||||
stub.getLibraryName = { library.name }
|
||||
result
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,19 @@
|
||||
package com.intellij.execution.junit;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.ExecutionBundle;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.testframework.SourceScope;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.JavaDirectoryService;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScopes;
|
||||
|
||||
@@ -80,14 +83,8 @@ class TestDirectory extends TestPackage {
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
if (myConfiguration.isAlternativeJrePathEnabled()) {
|
||||
if (myConfiguration.getAlternativeJrePath() == null ||
|
||||
myConfiguration.getAlternativeJrePath().length() == 0 ||
|
||||
!JavaSdk.checkForJre(myConfiguration.getAlternativeJrePath())) {
|
||||
throw new RuntimeConfigurationWarning(
|
||||
ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.mesage", myConfiguration.getAlternativeJrePath()));
|
||||
}
|
||||
}
|
||||
JavaParametersUtil.checkAlternativeJRE(myConfiguration);
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(myConfiguration, myConfiguration.getProject(), myConfiguration.getConfigurationModule().getModule());
|
||||
final String dirName = myConfiguration.getPersistentData().getDirName();
|
||||
if (dirName == null || dirName.isEmpty()) {
|
||||
throw new RuntimeConfigurationError("Directory is not specified");
|
||||
|
||||
@@ -36,13 +36,13 @@ import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
@@ -179,14 +179,8 @@ public abstract class TestObject implements JavaCommandLine {
|
||||
};
|
||||
|
||||
public void checkConfiguration() throws RuntimeConfigurationException{
|
||||
if (myConfiguration.isAlternativeJrePathEnabled()){
|
||||
if (myConfiguration.getAlternativeJrePath() == null ||
|
||||
myConfiguration.getAlternativeJrePath().length() == 0 ||
|
||||
!JavaSdk.checkForJre(myConfiguration.getAlternativeJrePath())){
|
||||
throw new RuntimeConfigurationWarning(
|
||||
ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.mesage", myConfiguration.getAlternativeJrePath()));
|
||||
}
|
||||
}
|
||||
JavaParametersUtil.checkAlternativeJRE(myConfiguration);
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(myConfiguration, myConfiguration.getProject(), myConfiguration.getConfigurationModule().getModule());
|
||||
}
|
||||
|
||||
public SourceScope getSourceScope() {
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.junit.RefactoringListeners;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.testframework.SourceScope;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.SettingsEditor;
|
||||
@@ -338,6 +340,8 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
}
|
||||
}
|
||||
JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this);
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(this, getProject(), getConfigurationModule().getModule());
|
||||
JavaParametersUtil.checkAlternativeJRE(this);
|
||||
//TODO add various checks here
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ public class TestNGResults extends TestResultsPanel implements TestFrameworkRunn
|
||||
dups.add(proxy);
|
||||
}
|
||||
}
|
||||
final String testMethodDescriptor = result.getTestClass() + result.getMethod();
|
||||
final String testMethodDescriptor = TestProxy.toDisplayText(result, project);
|
||||
if (startedMethods.contains(testMethodDescriptor)) {
|
||||
total++;
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ public class TestNGUtil
|
||||
}
|
||||
|
||||
public static final String TEST_ANNOTATION_FQN = Test.class.getName();
|
||||
public static final String FACTORY_ANNOTATION_FQN = Factory.class.getName();
|
||||
public static final String[] CONFIG_ANNOTATIONS_FQN = {
|
||||
Configuration.class.getName(),
|
||||
Factory.class.getName(),
|
||||
@@ -199,6 +200,7 @@ public class TestNGUtil
|
||||
PsiClass psiClass = (PsiClass) element;
|
||||
for (PsiMethod method : psiClass.getAllMethods()) {
|
||||
if (AnnotationUtil.isAnnotated(method, TEST_ANNOTATION_FQN, false, true)) return true;
|
||||
if (AnnotationUtil.isAnnotated(method, FACTORY_ANNOTATION_FQN, false, true)) return true;
|
||||
if (hasTestJavaDoc(method, checkJavadoc)) return true;
|
||||
}
|
||||
} else if (element instanceof PsiMethod) {
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.uiDesigner.wizard.BeanStep">
|
||||
<grid id="2ea7d" binding="myComponent" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="2ea7d" binding="myComponent" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="120" y="88" width="383" height="210"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0"/>
|
||||
<xy x="120" y="88" width="450" height="210"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="bdf40" class="javax.swing.JRadioButton" binding="myRbBindToNewBean">
|
||||
<constraints>
|
||||
<xy x="2" y="2" width="110" height="22"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0"/>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/UIDesignerBundle" key="radio.create.new.bean"/>
|
||||
@@ -20,26 +18,24 @@
|
||||
</component>
|
||||
<component id="d00f2" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<xy x="22" y="32" width="33" height="14"/>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0"/>
|
||||
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="9326f"/>
|
||||
<text resource-bundle="messages/UIDesignerBundle" key="editbox.class"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="9326f" class="javax.swing.JTextField" binding="myTfShortClassName">
|
||||
<constraints>
|
||||
<xy x="80" y="29" width="301" height="20"/>
|
||||
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0"/>
|
||||
<grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<columns value="25"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="370ca" class="javax.swing.JLabel">
|
||||
<component id="370ca" class="javax.swing.JLabel" binding="myPackageLabel">
|
||||
<constraints>
|
||||
<xy x="22" y="57" width="48" height="14"/>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0"/>
|
||||
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<inheritsPopupMenu value="true"/>
|
||||
@@ -48,31 +44,27 @@
|
||||
</component>
|
||||
<hspacer id="c7908">
|
||||
<constraints>
|
||||
<xy x="2" y="33" width="20" height="11"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0">
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="20" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<hspacer id="50aef">
|
||||
<constraints>
|
||||
<xy x="2" y="130" width="20" height="11"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0"/>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</hspacer>
|
||||
<component id="412f8" class="javax.swing.JRadioButton" binding="myRbBindToExistingBean">
|
||||
<constraints>
|
||||
<xy x="2" y="99" width="127" height="22"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/UIDesignerBundle" key="radio.bind.to.existing.bean"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="cc4af" class="javax.swing.JLabel">
|
||||
<component id="cc4af" class="javax.swing.JLabel" binding="myExistClassLabel">
|
||||
<constraints>
|
||||
<xy x="22" y="129" width="33" height="14"/>
|
||||
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0"/>
|
||||
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/UIDesignerBundle" key="editbox.class.2"/>
|
||||
@@ -80,29 +72,25 @@
|
||||
</component>
|
||||
<component id="9b7be" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myTfWitgBtnChooseClass">
|
||||
<constraints>
|
||||
<xy x="80" y="126" width="301" height="20"/>
|
||||
<grid row="5" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0"/>
|
||||
<grid row="5" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<vspacer id="3b24c">
|
||||
<constraints>
|
||||
<xy x="40" y="146" width="11" height="62"/>
|
||||
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0"/>
|
||||
<grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<vspacer id="6822f">
|
||||
<constraints>
|
||||
<xy x="40" y="79" width="11" height="20"/>
|
||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0">
|
||||
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="-1" height="20"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="45bb6" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myTfWithBtnChoosePackage">
|
||||
<constraints>
|
||||
<xy x="80" y="54" width="301" height="20"/>
|
||||
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0"/>
|
||||
<grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user