mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -256,7 +256,10 @@ public class UnscrambleDialog extends DialogWrapper{
|
||||
|
||||
static String normalizeText(@NonNls String text) {
|
||||
StringBuilder builder = new StringBuilder(text.length());
|
||||
|
||||
text = text.replaceAll("(\\S[ \\t\\x0B\\f\\r]+)(at\\s+)", "$1\n$2");
|
||||
String[] lines = text.split("\n");
|
||||
|
||||
boolean first = true;
|
||||
boolean inAuxInfo = false;
|
||||
for (String line : lines) {
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.intellij.psi.util;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.ElementManipulators;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -63,8 +66,7 @@ public abstract class ReferenceSetBase<T extends PsiReference> {
|
||||
do {
|
||||
next = findNextSeparator(str, current);
|
||||
final TextRange range = new TextRange(offset + current + 1, offset + (next > 0 ? next : str.length()));
|
||||
final T ref = createReference(range, index++);
|
||||
references.add(ref);
|
||||
references.addAll(createReferences(range, index ++));
|
||||
} while ((current = next) >= 0);
|
||||
|
||||
return references;
|
||||
@@ -76,8 +78,16 @@ public abstract class ReferenceSetBase<T extends PsiReference> {
|
||||
return next;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract T createReference(final TextRange range, final int index);
|
||||
@Nullable
|
||||
protected T createReference(final TextRange range, final int index) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected List<T> createReferences(final TextRange range, final int index) {
|
||||
T reference = createReference(range, index);
|
||||
|
||||
return reference == null? Collections.<T>emptyList() : Collections.singletonList(reference);
|
||||
}
|
||||
|
||||
public PsiElement getElement() {
|
||||
return myElement;
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -206,15 +207,9 @@ public class BookmarksAction extends AnAction implements DumbAware {
|
||||
list.clearSelection();
|
||||
}
|
||||
|
||||
new ListSpeedSearch(list) {
|
||||
@Override
|
||||
protected String getElementText(Object element) {
|
||||
return ((ItemWrapper)element).speedSearchText();
|
||||
}
|
||||
};
|
||||
|
||||
list.setCellRenderer(new ItemRenderer(project));
|
||||
|
||||
|
||||
JPanel footerPanel = new JPanel(new BorderLayout()) {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
@@ -248,7 +243,12 @@ public class BookmarksAction extends AnAction implements DumbAware {
|
||||
setSouthComponent(footerPanel).
|
||||
setEastComponent(previewPanel).
|
||||
setItemChoosenCallback(runnable).
|
||||
createPopup();
|
||||
setItemsNamer(new Function<Object, String>() {
|
||||
public String fun(Object o) {
|
||||
return ((ItemWrapper)o).speedSearchText();
|
||||
}
|
||||
}).createPopup();
|
||||
|
||||
editDescriptionAction.setPopup(popup);
|
||||
popup.showCenteredInCurrentWindow(project);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.ui.ListScrollingUtil;
|
||||
import com.intellij.ui.speedSearch.ListWithFilter;
|
||||
import com.intellij.ui.treeStructure.treetable.TreeTable;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -68,6 +70,8 @@ public class PopupChooserBuilder {
|
||||
private Component mySettingsButtons;
|
||||
private boolean myAutoselectOnMouseMove = true;
|
||||
|
||||
private Function<Object,String> myItemsNamer = null;
|
||||
|
||||
public PopupChooserBuilder(@NotNull JList list) {
|
||||
myChooserComponent = list;
|
||||
}
|
||||
@@ -153,11 +157,16 @@ public class PopupChooserBuilder {
|
||||
myAutoselectOnMouseMove = doAutoSelect;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PopupChooserBuilder setItemsNamer(Function<Object, String> namer) {
|
||||
myItemsNamer = namer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JBPopup createPopup() {
|
||||
if (myChooserComponent instanceof JList) {
|
||||
myChooserComponent = new MyListWrapper((JList)myChooserComponent);
|
||||
myChooserComponent = ListWithFilter.wrap((JList)myChooserComponent, new MyListWrapper((JList)myChooserComponent), myItemsNamer);
|
||||
}
|
||||
|
||||
JPanel contentPane = new JPanel(new BorderLayout());
|
||||
@@ -168,8 +177,8 @@ public class PopupChooserBuilder {
|
||||
contentPane.add(label, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
if (myChooserComponent instanceof MyListWrapper) {
|
||||
JList list = ((MyListWrapper)myChooserComponent).myList;
|
||||
if (myChooserComponent instanceof ListWithFilter) {
|
||||
JList list = ((ListWithFilter)myChooserComponent).getList();
|
||||
if (list.getSelectedIndex() == -1 && myAutoselect) {
|
||||
list.setSelectedIndex(0);
|
||||
}
|
||||
@@ -193,8 +202,8 @@ public class PopupChooserBuilder {
|
||||
}
|
||||
|
||||
final JScrollPane scrollPane;
|
||||
if (myChooserComponent instanceof MyListWrapper) {
|
||||
scrollPane = (MyListWrapper)myChooserComponent;
|
||||
if (myChooserComponent instanceof ListWithFilter) {
|
||||
scrollPane = ((ListWithFilter)myChooserComponent).getScrollPane();
|
||||
}
|
||||
else if (myChooserComponent instanceof JTable) {
|
||||
scrollPane = createScrollPane((JTable)myChooserComponent);
|
||||
@@ -207,7 +216,13 @@ public class PopupChooserBuilder {
|
||||
}
|
||||
|
||||
scrollPane.getViewport().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
contentPane.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
if (myChooserComponent instanceof ListWithFilter) {
|
||||
contentPane.add(myChooserComponent, BorderLayout.CENTER);
|
||||
}
|
||||
else {
|
||||
contentPane.add(scrollPane, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
if (mySouthComponent != null) {
|
||||
contentPane.add(mySouthComponent, BorderLayout.SOUTH);
|
||||
@@ -224,7 +239,9 @@ public class PopupChooserBuilder {
|
||||
|
||||
builder.setDimensionServiceKey(null, myDimensionServiceKey, false).setRequestFocus(myRequestFocus).setResizable(myForceResizable)
|
||||
.setMovable(myForceMovable).setTitle(myForceMovable ? myTitle : null).setCancelCallback(myCancelCallback).setAlpha(myAlpha)
|
||||
.setFocusOwners(myFocusOwners).setCancelKeyEnabled(myCancelKeyEnabled).setAdText(myAd).setKeyboardActions(myKeyboardActions);
|
||||
.setFocusOwners(myFocusOwners).setCancelKeyEnabled(myCancelKeyEnabled && !(myChooserComponent instanceof ListWithFilter)).
|
||||
setAdText(myAd).setKeyboardActions(myKeyboardActions);
|
||||
|
||||
if (myCommandButton != null) {
|
||||
builder.setCommandButton(myCommandButton);
|
||||
}
|
||||
@@ -252,6 +269,9 @@ public class PopupChooserBuilder {
|
||||
private void registerClosePopupKeyboardAction(final KeyStroke keyStroke, final boolean shouldPerformAction) {
|
||||
myChooserComponent.registerKeyboardAction(new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!shouldPerformAction && myChooserComponent instanceof ListWithFilter) {
|
||||
if (((ListWithFilter)myChooserComponent).resetFilter()) return;
|
||||
}
|
||||
closePopup(shouldPerformAction, null);
|
||||
}
|
||||
}, keyStroke, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.ui.speedSearch;
|
||||
|
||||
import com.intellij.openapi.util.Condition;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListDataEvent;
|
||||
import javax.swing.event.ListDataListener;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class FilteringListModel<T> extends DefaultListModel {
|
||||
private final JList myList;
|
||||
private final ListModel myOriginalModel;
|
||||
private Condition<T> myCondition = null;
|
||||
|
||||
private final ListDataListener myListDataListener = new ListDataListener() {
|
||||
public void contentsChanged(ListDataEvent e) {
|
||||
refilter();
|
||||
}
|
||||
|
||||
public void intervalAdded(ListDataEvent e) {
|
||||
refilter();
|
||||
}
|
||||
|
||||
public void intervalRemoved(ListDataEvent e) {
|
||||
refilter();
|
||||
}
|
||||
};
|
||||
|
||||
protected FilteringListModel(JList list) {
|
||||
myList = list;
|
||||
myOriginalModel = list.getModel();
|
||||
myOriginalModel.addListDataListener(myListDataListener);
|
||||
refilter();
|
||||
|
||||
list.setModel(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myOriginalModel.removeListDataListener(myListDataListener);
|
||||
}
|
||||
|
||||
public void setFilter(Condition<T> condition) {
|
||||
myCondition = condition;
|
||||
refilter();
|
||||
}
|
||||
|
||||
public void refilter() {
|
||||
removeAllElements();
|
||||
for (int i = 0; i < myOriginalModel.getSize(); i++) {
|
||||
final T elt = (T)myOriginalModel.getElementAt(i);
|
||||
if (passElement(elt)) {
|
||||
addToFiltered(elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void addToFiltered(T elt) {
|
||||
addElement(elt);
|
||||
}
|
||||
|
||||
private boolean passElement(T element) {
|
||||
return myCondition == null || myCondition.value(element);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.ui.speedSearch;
|
||||
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.ui.LightColors;
|
||||
import com.intellij.util.Function;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class ListWithFilter<T> extends JPanel {
|
||||
private final JList myList;
|
||||
private final JTextField mySpeedSearchPatternField;
|
||||
private final NameFilteringListModel<T> myModel;
|
||||
private final JScrollPane myScroller;
|
||||
private final MySpeedSearch mySpeedSearch;
|
||||
|
||||
public static JComponent wrap(JList list) {
|
||||
return wrap(list, new JScrollPane(list), new Function<Object, String>() {
|
||||
public String fun(Object o) {
|
||||
return o.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> JComponent wrap(JList list, JScrollPane scroller, Function<T, String> namer) {
|
||||
return new ListWithFilter<T>(list, scroller, namer);
|
||||
}
|
||||
|
||||
private ListWithFilter(JList list, JScrollPane scroller, Function<T, String> namer) {
|
||||
super(new BorderLayout());
|
||||
|
||||
myList = list;
|
||||
myScroller = scroller;
|
||||
|
||||
mySpeedSearchPatternField = new JTextField();
|
||||
mySpeedSearchPatternField.setFocusable(false);
|
||||
mySpeedSearchPatternField.setVisible(false);
|
||||
|
||||
add(mySpeedSearchPatternField, BorderLayout.NORTH);
|
||||
add(myScroller, BorderLayout.CENTER);
|
||||
|
||||
mySpeedSearch = new MySpeedSearch();
|
||||
mySpeedSearch.setEnabled(namer != null);
|
||||
|
||||
myList.addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(final KeyEvent e) {
|
||||
mySpeedSearch.process(e);
|
||||
}
|
||||
});
|
||||
|
||||
myModel = new NameFilteringListModel<T>(myList, namer, new Condition<String>() {
|
||||
public boolean value(String s) {
|
||||
return mySpeedSearch.shouldBeShowing(s);
|
||||
}
|
||||
}, mySpeedSearch);
|
||||
|
||||
setBackground(list.getBackground());
|
||||
setFocusable(true);
|
||||
}
|
||||
|
||||
public boolean resetFilter() {
|
||||
boolean hadPattern = mySpeedSearch.isHoldingFilter();
|
||||
mySpeedSearch.reset();
|
||||
return hadPattern;
|
||||
}
|
||||
|
||||
private class MySpeedSearch extends SpeedSearch {
|
||||
boolean searchFieldShown = false;
|
||||
|
||||
protected void update() {
|
||||
mySpeedSearchPatternField.setBackground(new JTextField().getBackground());
|
||||
onSpeedSearchPatternChanged();
|
||||
mySpeedSearchPatternField.setText(getFilter());
|
||||
if (isHoldingFilter() && !searchFieldShown) {
|
||||
mySpeedSearchPatternField.setVisible(true);
|
||||
searchFieldShown = true;
|
||||
revalidate();
|
||||
}
|
||||
else if (!isHoldingFilter() && searchFieldShown) {
|
||||
mySpeedSearchPatternField.setVisible(false);
|
||||
searchFieldShown = false;
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onSpeedSearchPatternChanged() {
|
||||
myModel.refilter();
|
||||
if (myModel.getSize() > 0) {
|
||||
int fullMatchIndex = myModel.getClosestMatchIndex();
|
||||
if (fullMatchIndex != -1) {
|
||||
myList.setSelectedIndex(fullMatchIndex);
|
||||
}
|
||||
|
||||
if (myModel.getSize() <= myList.getSelectedIndex() || !myModel.contains(myList.getSelectedValue())) {
|
||||
myList.setSelectedIndex(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mySpeedSearchPatternField.setBackground(LightColors.RED);
|
||||
}
|
||||
}
|
||||
|
||||
public JList getList() {
|
||||
return myList;
|
||||
}
|
||||
|
||||
public JScrollPane getScrollPane() {
|
||||
return myScroller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestFocus() {
|
||||
myList.requestFocus();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.ui.speedSearch;
|
||||
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.util.Function;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class NameFilteringListModel<T> extends FilteringListModel<T> {
|
||||
private final Function<T, String> myNamer;
|
||||
|
||||
private int myFullMatchIndex = -1;
|
||||
private int myStartsWithIndex = -1;
|
||||
private final SpeedSearch mySpeedSearch;
|
||||
|
||||
public NameFilteringListModel(JList list, final Function<T, String> namer, final Condition<String> filter,
|
||||
SpeedSearch speedSearch) {
|
||||
super(list);
|
||||
mySpeedSearch = speedSearch;
|
||||
setFilter(namer != null ? new Condition<T>() {
|
||||
public boolean value(T t) {
|
||||
return filter.value(namer.fun(t));
|
||||
}
|
||||
} : null);
|
||||
myNamer = namer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addToFiltered(T elt) {
|
||||
super.addToFiltered(elt);
|
||||
|
||||
String filterString = mySpeedSearch.getFilter().toUpperCase();
|
||||
String candidateString = myNamer.fun(elt).toUpperCase();
|
||||
int index = size() - 1;
|
||||
|
||||
if (myFullMatchIndex == -1 && filterString.equals(candidateString)) {
|
||||
myFullMatchIndex = index;
|
||||
}
|
||||
|
||||
if (myStartsWithIndex == -1 && candidateString.startsWith(filterString)) {
|
||||
myStartsWithIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refilter() {
|
||||
myFullMatchIndex = -1;
|
||||
myStartsWithIndex = -1;
|
||||
super.refilter();
|
||||
}
|
||||
|
||||
public int getClosestMatchIndex() {
|
||||
return myFullMatchIndex != -1 ? myFullMatchIndex : myStartsWithIndex;
|
||||
}
|
||||
}
|
||||
+13
-18
@@ -32,9 +32,9 @@ import com.intellij.openapi.vcs.FileStatusManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.ColoredListCellRenderer;
|
||||
import com.intellij.ui.LightColors;
|
||||
import com.intellij.ui.ListSpeedSearch;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IconUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -163,7 +163,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
|
||||
if (list.getModel().getSize() == 0) {
|
||||
list.clearSelection();
|
||||
}
|
||||
new MyListSpeedSearch(list);
|
||||
|
||||
list.setCellRenderer(new RecentFilesRenderer(project));
|
||||
|
||||
/*
|
||||
@@ -189,12 +189,17 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
|
||||
footerPanel.add(pathLabel);
|
||||
|
||||
new PopupChooserBuilder(list).
|
||||
setTitle(getTitle()).
|
||||
setMovable(true).
|
||||
setSouthComponent(footerPanel).
|
||||
setItemChoosenCallback(runnable).
|
||||
addAdditionalChooseKeystroke(getAdditionalSelectKeystroke()).
|
||||
createPopup().showCenteredInCurrentWindow(project);
|
||||
setTitle(getTitle()).
|
||||
setMovable(true).
|
||||
setSouthComponent(footerPanel).
|
||||
setItemChoosenCallback(runnable).
|
||||
addAdditionalChooseKeystroke(getAdditionalSelectKeystroke()).
|
||||
setItemsNamer(new Function<Object, String>() {
|
||||
public String fun(Object o) {
|
||||
return o instanceof VirtualFile ? ((VirtualFile)o).getName() : "";
|
||||
}
|
||||
}).
|
||||
createPopup().showCenteredInCurrentWindow(project);
|
||||
}
|
||||
|
||||
protected abstract String getTitle();
|
||||
@@ -234,14 +239,4 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyListSpeedSearch extends ListSpeedSearch {
|
||||
public MyListSpeedSearch(JList list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
protected String getElementText(Object element) {
|
||||
return element instanceof VirtualFile ? ((VirtualFile)element).getName() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="git4idea.checkin.GitConvertFilesDialog">
|
||||
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="514" height="273"/>
|
||||
@@ -34,21 +34,13 @@
|
||||
</scrollpane>
|
||||
<component id="4471d" class="javax.swing.JCheckBox" binding="myDoNotShowCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="common.do.not.show"/>
|
||||
<toolTipText resource-bundle="git4idea/i18n/GitBundle" key="common.do.not.show.tooltip"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="8c724" class="javax.swing.JCheckBox" binding="myDoNotConvertFilesCheckBox" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="git4idea/i18n/GitBundle" key="crlf.convert.none"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.codeStyle.CodeStyleFacade;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -29,15 +30,16 @@ import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.commands.GitHandler;
|
||||
import git4idea.commands.GitSimpleHandler;
|
||||
import git4idea.commands.StringScanner;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
import git4idea.config.GitVersion;
|
||||
import git4idea.i18n.GitBundle;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
@@ -47,6 +49,14 @@ import java.util.*;
|
||||
* This dialog allows converting the specified files before committing them.
|
||||
*/
|
||||
public class GitConvertFilesDialog extends DialogWrapper {
|
||||
/**
|
||||
* The version when option --stdin was added
|
||||
*/
|
||||
private static final GitVersion CHECK_ATTR_STDIN_SUPPORTED = new GitVersion(1, 6, 1, 0);
|
||||
/**
|
||||
* Do not convert exit code
|
||||
*/
|
||||
public static final int DO_NOT_CONVERT = NEXT_USER_EXIT_CODE;
|
||||
/**
|
||||
* The checkbox used to indicate that dialog should not be shown
|
||||
*/
|
||||
@@ -55,10 +65,6 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
* The root panel of the dialog
|
||||
*/
|
||||
private JPanel myRootPanel;
|
||||
/**
|
||||
* The checkbox that disables conversion of files
|
||||
*/
|
||||
private JCheckBox myDoNotConvertFilesCheckBox;
|
||||
/**
|
||||
* The tree of files to convert
|
||||
*/
|
||||
@@ -73,7 +79,7 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
*
|
||||
* @param project the project to which this dialog is related
|
||||
*/
|
||||
GitConvertFilesDialog(Project project, GitVcsSettings settings, Map<VirtualFile, Set<VirtualFile>> filesToShow) {
|
||||
GitConvertFilesDialog(Project project, Map<VirtualFile, Set<VirtualFile>> filesToShow) {
|
||||
super(project, true);
|
||||
ArrayList<VirtualFile> roots = new ArrayList<VirtualFile>(filesToShow.keySet());
|
||||
Collections.sort(roots, GitUtil.VIRTUAL_FILE_COMPARATOR);
|
||||
@@ -86,33 +92,18 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
vcsRoot.add(new CheckedTreeNode(file));
|
||||
}
|
||||
}
|
||||
myDoNotConvertFilesCheckBox.setSelected(settings.LINE_SEPARATORS_CONVERSION == GitVcsSettings.ConversionPolicy.NONE);
|
||||
updateFields();
|
||||
TreeUtil.expandAll(myFilesToConvert);
|
||||
myDoNotConvertFilesCheckBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateFields();
|
||||
}
|
||||
});
|
||||
setTitle(GitBundle.getString("crlf.convert.title"));
|
||||
setOKButtonText(GitBundle.getString("crlf.convert.convert"));
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update fields basing on selection state
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private void updateFields() {
|
||||
if (myDoNotConvertFilesCheckBox.isSelected()) {
|
||||
myRootNode.setChecked(false);
|
||||
myFilesToConvert.setEnabled(false);
|
||||
setOKButtonText(GitBundle.getString("crlf.convert.leave"));
|
||||
}
|
||||
else {
|
||||
myFilesToConvert.setEnabled(true);
|
||||
myRootNode.setChecked(true);
|
||||
setOKButtonText(GitBundle.getString("crlf.convert.convert"));
|
||||
}
|
||||
@Override
|
||||
protected Action[] createActions() {
|
||||
return new Action[]{getOKAction(), new DoNotConvertAction(), getCancelAction()};
|
||||
}
|
||||
|
||||
|
||||
@@ -199,27 +190,19 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
if (files.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
final Ref<VirtualFile[]> selectedFiles = new Ref<VirtualFile[]>();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
GitConvertFilesDialog d = new GitConvertFilesDialog(project, settings, files);
|
||||
GitConvertFilesDialog d = new GitConvertFilesDialog(project, files);
|
||||
d.show();
|
||||
if (d.isOK()) {
|
||||
settings.LINE_SEPARATORS_CONVERSION_ASK = d.myDoNotShowCheckBox.isSelected();
|
||||
if (d.myDoNotConvertFilesCheckBox.isSelected()) {
|
||||
settings.LINE_SEPARATORS_CONVERSION = GitVcsSettings.ConversionPolicy.NONE;
|
||||
}
|
||||
else {
|
||||
settings.LINE_SEPARATORS_CONVERSION = GitVcsSettings.ConversionPolicy.PROJECT_LINE_SEPARATORS;
|
||||
for (VirtualFile f : d.myFilesToConvert.getCheckedNodes(VirtualFile.class, null)) {
|
||||
try {
|
||||
LoadTextUtil.changeLineSeparator(project, d, f, nl);
|
||||
}
|
||||
catch (IOException e) {
|
||||
//noinspection ThrowableInstanceNeverThrown
|
||||
exceptions.add(new VcsException("Failed to change line separators for the file: " + f.getPresentableUrl(), e));
|
||||
}
|
||||
}
|
||||
}
|
||||
settings.LINE_SEPARATORS_CONVERSION = GitVcsSettings.ConversionPolicy.PROJECT_LINE_SEPARATORS;
|
||||
selectedFiles.set(d.myFilesToConvert.getCheckedNodes(VirtualFile.class, null));
|
||||
}
|
||||
else if (d.getExitCode() == DO_NOT_CONVERT) {
|
||||
settings.LINE_SEPARATORS_CONVERSION_ASK = d.myDoNotShowCheckBox.isSelected();
|
||||
settings.LINE_SEPARATORS_CONVERSION = GitVcsSettings.ConversionPolicy.NONE;
|
||||
}
|
||||
else {
|
||||
//noinspection ThrowableInstanceNeverThrown
|
||||
@@ -227,6 +210,17 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
});
|
||||
if (selectedFiles.get() != null) {
|
||||
for (VirtualFile f : selectedFiles.get()) {
|
||||
try {
|
||||
LoadTextUtil.changeLineSeparator(project, GitConvertFilesDialog.class.getName(), f, nl);
|
||||
}
|
||||
catch (IOException e) {
|
||||
//noinspection ThrowableInstanceNeverThrown
|
||||
exceptions.add(new VcsException("Failed to change line separators for the file: " + f.getPresentableUrl(), e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (VcsException e) {
|
||||
@@ -243,10 +237,14 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
* @throws VcsException if there is problem with running git
|
||||
*/
|
||||
private static void ignoreFilesWithCrlfUnset(Project project, Map<VirtualFile, Set<VirtualFile>> files) throws VcsException {
|
||||
boolean stdin = GitVcs.getInstance(project).version().isLessOrEqual(CHECK_ATTR_STDIN_SUPPORTED);
|
||||
for (final Map.Entry<VirtualFile, Set<VirtualFile>> e : files.entrySet()) {
|
||||
final VirtualFile r = e.getKey();
|
||||
GitSimpleHandler h = new GitSimpleHandler(project, r, GitHandler.CHECK_ATTR);
|
||||
h.addParameters("--stdin", "-z", "crlf");
|
||||
if (stdin) {
|
||||
h.addParameters("--stdin", "-z");
|
||||
}
|
||||
h.addParameters("crlf");
|
||||
h.setSilent(true);
|
||||
h.setNoSSH(true);
|
||||
final HashMap<String, VirtualFile> filesToCheck = new HashMap<String, VirtualFile>();
|
||||
@@ -254,33 +252,39 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
for (VirtualFile file : fileSet) {
|
||||
filesToCheck.put(GitUtil.relativePath(r, file), file);
|
||||
}
|
||||
h.setInputProcessor(new Processor<OutputStream>() {
|
||||
public boolean process(OutputStream outputStream) {
|
||||
try {
|
||||
OutputStreamWriter out = new OutputStreamWriter(outputStream, GitUtil.UTF8_CHARSET);
|
||||
if (stdin) {
|
||||
h.setInputProcessor(new Processor<OutputStream>() {
|
||||
public boolean process(OutputStream outputStream) {
|
||||
try {
|
||||
for (String file : filesToCheck.keySet()) {
|
||||
out.write(file);
|
||||
out.write("\u0000");
|
||||
OutputStreamWriter out = new OutputStreamWriter(outputStream, GitUtil.UTF8_CHARSET);
|
||||
try {
|
||||
for (String file : filesToCheck.keySet()) {
|
||||
out.write(file);
|
||||
out.write("\u0000");
|
||||
}
|
||||
}
|
||||
finally {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
out.close();
|
||||
catch (IOException ex) {
|
||||
try {
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// ignore exception
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
try {
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// ignore exception
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
h.endOptions();
|
||||
h.addRelativeFiles(filesToCheck.values());
|
||||
}
|
||||
StringScanner output = new StringScanner(h.run());
|
||||
String unsetIndicator = ": crlf unset";
|
||||
String unsetIndicator = ": crlf: unset";
|
||||
while (output.hasMoreData()) {
|
||||
String l = output.line();
|
||||
if (l.endsWith(unsetIndicator)) {
|
||||
@@ -290,6 +294,35 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action used to indicate that no conversion should be performed
|
||||
*/
|
||||
class DoNotConvertAction extends AbstractAction {
|
||||
private static final long serialVersionUID = 1931383640152023206L;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
DoNotConvertAction() {
|
||||
putValue(NAME, GitBundle.getString("crlf.convert.leave"));
|
||||
putValue(DEFAULT_ACTION, Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (myPerformAction) return;
|
||||
try {
|
||||
myPerformAction = true;
|
||||
close(DO_NOT_CONVERT);
|
||||
}
|
||||
finally {
|
||||
myPerformAction = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The cell renderer for the tree
|
||||
@@ -330,11 +363,12 @@ public class GitConvertFilesDialog extends DialogWrapper {
|
||||
|
||||
/**
|
||||
* Render unknown node
|
||||
* @param r a renderer to use
|
||||
*
|
||||
* @param r a renderer to use
|
||||
* @param value the unknown value
|
||||
*/
|
||||
private static void renderUnknown(ColoredTreeCellRenderer r, Object value) {
|
||||
r.append("UNSUPPORTED NODE TYPE: "+(value == null?"null":value.getClass().getName()), SimpleTextAttributes.ERROR_ATTRIBUTES);
|
||||
r.append("UNSUPPORTED NODE TYPE: " + (value == null ? "null" : value.getClass().getName()), SimpleTextAttributes.ERROR_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ public class GitVcsPanel {
|
||||
mySSHExecutableComboBox.addItem(IDEA_SSH);
|
||||
mySSHExecutableComboBox.addItem(NATIVE_SSH);
|
||||
mySSHExecutableComboBox.setSelectedItem(GitVcsSettings.isDefaultIdeaSsh() ? IDEA_SSH : NATIVE_SSH);
|
||||
myAskBeforeConversionsCheckBox.setSelected(mySettings.LINE_SEPARATORS_CONVERSION_ASK);
|
||||
myTestButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
testConnection();
|
||||
@@ -175,7 +176,8 @@ public class GitVcsPanel {
|
||||
public boolean isModified(@NotNull GitVcsSettings settings) {
|
||||
return !settings.GIT_EXECUTABLE.equals(myGitField.getText()) ||
|
||||
(settings.isIdeaSsh() != IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem())) ||
|
||||
!crlfPolicyItem(settings).equals(myConvertTextFilesComboBox.getSelectedItem());
|
||||
!crlfPolicyItem(settings).equals(myConvertTextFilesComboBox.getSelectedItem()) ||
|
||||
settings.LINE_SEPARATORS_CONVERSION_ASK != myAskBeforeConversionsCheckBox.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,13 +190,16 @@ public class GitVcsPanel {
|
||||
settings.setIdeaSsh(IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem()));
|
||||
Object policyItem = myConvertTextFilesComboBox.getSelectedItem();
|
||||
GitVcsSettings.ConversionPolicy conversionPolicy;
|
||||
if(CRLF_DO_NOT_CONVERT.equals(policyItem)) {
|
||||
if (CRLF_DO_NOT_CONVERT.equals(policyItem)) {
|
||||
conversionPolicy = GitVcsSettings.ConversionPolicy.NONE;
|
||||
} else if (CRLF_CONVERT_TO_PROJECT.equals(policyItem)) {
|
||||
}
|
||||
else if (CRLF_CONVERT_TO_PROJECT.equals(policyItem)) {
|
||||
conversionPolicy = GitVcsSettings.ConversionPolicy.PROJECT_LINE_SEPARATORS;
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown selected CRLF policy: "+policyItem);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown selected CRLF policy: " + policyItem);
|
||||
}
|
||||
settings.LINE_SEPARATORS_CONVERSION = conversionPolicy;
|
||||
settings.LINE_SEPARATORS_CONVERSION_ASK = myAskBeforeConversionsCheckBox.isSelected();
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -230,7 +230,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
assertion.accept(this);
|
||||
final InstructionImpl assertInstruction = startNode(assertStatement);
|
||||
final PsiType type = JavaPsiFacade.getInstance(assertStatement.getProject()).getElementFactory()
|
||||
.createTypeByFQClassName("java.lang.AssertionError", assertStatement.getResolveScope());
|
||||
.createTypeByFQClassName("java.lang.AssertionError", assertStatement.getResolveScope());
|
||||
ExceptionInfo info = findCatch(type);
|
||||
if (info != null) {
|
||||
info.myThrowers.add(assertInstruction);
|
||||
@@ -294,7 +294,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
if (expression.getOperationToken() != GroovyElementTypes.mASSIGN) {
|
||||
if (lValue instanceof GrReferenceExpression) {
|
||||
ReadWriteVariableInstructionImpl instruction =
|
||||
new ReadWriteVariableInstructionImpl((GrReferenceExpression)lValue, myInstructionNumber++, false);
|
||||
new ReadWriteVariableInstructionImpl((GrReferenceExpression)lValue, myInstructionNumber++, false);
|
||||
addNode(instruction);
|
||||
checkPending(instruction);
|
||||
}
|
||||
@@ -339,7 +339,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
}
|
||||
else {
|
||||
final ReadWriteVariableInstructionImpl i =
|
||||
new ReadWriteVariableInstructionImpl(referenceExpression, myInstructionNumber++, PsiUtil.isLValue(referenceExpression));
|
||||
new ReadWriteVariableInstructionImpl(referenceExpression, myInstructionNumber++, PsiUtil.isLValue(referenceExpression));
|
||||
addNode(i);
|
||||
checkPending(i);
|
||||
}
|
||||
@@ -398,6 +398,11 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
|
||||
if (expression != null) {
|
||||
expression.accept(this);
|
||||
}
|
||||
for (GrVariable variable : clause.getDeclaredVariables()) {
|
||||
ReadWriteVariableInstructionImpl writeInsn = new ReadWriteVariableInstructionImpl(variable, myInstructionNumber++);
|
||||
checkPending(writeInsn);
|
||||
addNode(writeInsn);
|
||||
}
|
||||
}
|
||||
|
||||
InstructionImpl instruction = startNode(forStatement);
|
||||
|
||||
+1
@@ -86,5 +86,6 @@ public class ExtractMethodTest extends LightGroovyTestCase {
|
||||
public void testVen1() throws Throwable { doTest(); }
|
||||
public void testVen2() throws Throwable { doTest(); }
|
||||
public void testVen3() throws Throwable { doTest(); }
|
||||
public void testForIn() throws Throwable { doTest(); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
void aaa(Map map) {
|
||||
for (Map.Entry<String, String> versionEntry in map.entrySet()) {
|
||||
<begin>String name = versionEntry.getKey();
|
||||
System.out.println(name);<end>
|
||||
}
|
||||
}
|
||||
-----
|
||||
import java.util.Map.Entry
|
||||
|
||||
void aaa(Map map) {
|
||||
for (Map.Entry<String, String> versionEntry in map.entrySet()) {
|
||||
testMethod(versionEntry);
|
||||
}
|
||||
}
|
||||
|
||||
private def testMethod(Entry<String, String> versionEntry) {
|
||||
String name = versionEntry.getKey();
|
||||
System.out.println(name)
|
||||
}
|
||||
Reference in New Issue
Block a user