diff --git a/build/conf/nsis/desktop.ini b/build/conf/nsis/desktop.ini index 8f590b778e84..41eef313f4d9 100644 --- a/build/conf/nsis/desktop.ini +++ b/build/conf/nsis/desktop.ini @@ -23,7 +23,7 @@ Left=1 Right=-1 Top=35 Bottom=65 -Text=Create Associations +Text=Create associations [Field 4] Type=checkbox diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java index 89cc49eb820a..42effb123dd6 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ClasspathEditor.java @@ -29,7 +29,6 @@ import com.intellij.openapi.roots.impl.storage.ClasspathStorage; import com.intellij.openapi.roots.impl.storage.ClasspathStorageProvider; import com.intellij.openapi.roots.ui.configuration.classpath.ClasspathPanelImpl; import com.intellij.openapi.util.Disposer; -import com.intellij.ui.OrderPanelListener; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -77,7 +76,6 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL @Override public void saveData() { myPanel.stopEditing(); - flushChangesToModel(); } @Override @@ -99,14 +97,6 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL @Override public JComponent createComponentImpl() { myPanel = new ClasspathPanelImpl(getState()); - - myPanel.addListener(new OrderPanelListener() { - @Override - public void entryMoved() { - flushChangesToModel(); - } - }); - final JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6)); panel.add(myPanel, BorderLayout.CENTER); @@ -131,9 +121,8 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL return panel; } + @Deprecated public void flushChangesToModel() { - List entries = myPanel.getEntries(); - getModel().rearrangeOrderEntries(entries.toArray(new OrderEntry[entries.size()])); } public void selectOrderEntry(@NotNull final OrderEntry entry) { @@ -170,8 +159,6 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL if (myPanel != null) { myPanel.forceInitFromModel(); } - - flushChangesToModel(); } private class ClasspathFormatPanel extends JPanel { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java index 25108a7c5c1a..4b80cc59e557 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java @@ -46,6 +46,7 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryPro import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.SdkProjectStructureElement; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.ComboBoxTableRenderer; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopup; @@ -63,7 +64,9 @@ import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.table.JBTable; import com.intellij.util.EventDispatcher; import com.intellij.util.IconUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.TextTransferable; +import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -73,15 +76,16 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import java.awt.*; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; -import java.util.ArrayList; +import java.util.*; import java.util.List; -import java.util.Set; public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.classpath.ClasspathPanelImpl"); @@ -98,7 +102,27 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { myState = state; myModel = new ClasspathTableModel(state, getStructureConfigurableContext()); - myEntryTable = new JBTable(myModel); + myEntryTable = new JBTable(myModel) { + @Override + protected TableRowSorter createRowSorter(TableModel model) { + return new DefaultColumnInfoBasedRowSorter(model) { + @Override + public void toggleSortOrder(int column) { + if (isSortable(column)) { + SortKey oldKey = ContainerUtil.getFirstItem(getSortKeys()); + SortOrder oldOrder; + if (oldKey == null || oldKey.getColumn() != column) { + oldOrder = SortOrder.UNSORTED; + } + else { + oldOrder = oldKey.getSortOrder(); + } + setSortKeys(Collections.singletonList(new SortKey(column, getNextSortOrder(oldOrder)))); + } + } + }; + } + }; myEntryTable.setShowGrid(false); myEntryTable.setDragEnabled(false); myEntryTable.setIntercellSpacing(new Dimension(0, 0)); @@ -106,7 +130,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { myEntryTable.setDefaultRenderer(ClasspathTableItem.class, new TableItemRenderer(getStructureConfigurableContext())); myEntryTable.setDefaultRenderer(Boolean.class, new ExportFlagRenderer(myEntryTable.getDefaultRenderer(Boolean.class))); - JComboBox scopeEditor = new JComboBox(new EnumComboBoxModel(DependencyScope.class)); + JComboBox scopeEditor = new ComboBox(new EnumComboBoxModel(DependencyScope.class)); myEntryTable.setDefaultEditor(DependencyScope.class, new DefaultCellEditor(scopeEditor)); myEntryTable.setDefaultRenderer(DependencyScope.class, new ComboBoxTableRenderer(DependencyScope.values()) { @Override @@ -149,7 +173,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { final int count = myModel.getRowCount(); Object[] elements = new Object[count]; for (int idx = 0; idx < count; idx++) { - elements[idx] = myModel.getItemAt(idx); + elements[idx] = myModel.getItem(idx); } return elements; } @@ -163,7 +187,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { public void selectElement(Object element, String selectedText) { final int count = myModel.getRowCount(); for (int row = 0; row < count; row++) { - if (element.equals(myModel.getItemAt(row))) { + if (element.equals(myModel.getItem(row))) { final int viewRow = myEntryTable.convertRowIndexToView(row); myEntryTable.getSelectionModel().setSelectionInterval(viewRow, viewRow); TableUtil.scrollSelectionToVisible(myEntryTable); @@ -172,8 +196,8 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { } } }; - setFixedColumnWidth(ClasspathTableModel.EXPORT_COLUMN, ClasspathTableModel.EXPORT_COLUMN_NAME); - setFixedColumnWidth(ClasspathTableModel.SCOPE_COLUMN, DependencyScope.COMPILE.toString() + " "); // leave space for combobox border + setFixedColumnWidth(ClasspathTableModel.EXPORT_COLUMN); + setFixedColumnWidth(ClasspathTableModel.SCOPE_COLUMN); // leave space for combobox border myEntryTable.registerKeyboardAction( new ActionListener() { @@ -182,14 +206,14 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { final int[] selectedRows = myEntryTable.getSelectedRows(); boolean currentlyMarked = true; for (final int selectedRow : selectedRows) { - final ClasspathTableItem item = myModel.getItemAt(myEntryTable.convertRowIndexToModel(selectedRow)); + final ClasspathTableItem item = getItemAt(selectedRow); if (selectedRow < 0 || !item.isExportable()) { return; } currentlyMarked &= item.isExported(); } for (final int selectedRow : selectedRows) { - myModel.getItemAt(myEntryTable.convertRowIndexToModel(selectedRow)).setExported(!currentlyMarked); + getItemAt(selectedRow).setExported(!currentlyMarked); } myModel.fireTableDataChanged(); TableUtil.selectRows(myEntryTable, selectedRows); @@ -256,6 +280,23 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { PopupHandler.installPopupHandler(myEntryTable, actionGroup, ActionPlaces.UNKNOWN, ActionManager.getInstance()); } + @NotNull + private static SortOrder getNextSortOrder(@NotNull SortOrder order) { + switch (order) { + case ASCENDING: + return SortOrder.DESCENDING; + case DESCENDING: + return SortOrder.UNSORTED; + case UNSORTED: + default: + return SortOrder.ASCENDING; + } + } + + private ClasspathTableItem getItemAt(int selectedRow) { + return myModel.getItem(myEntryTable.convertRowIndexToModel(selectedRow)); + } + private void addChangeLibraryLevelAction(DefaultActionGroup actionGroup, String tableLevel) { final LibraryTablePresentation presentation = LibraryEditingUtil.getLibraryTablePresentation(getProject(), tableLevel); actionGroup.add(new ChangeLibraryLevelInClasspathAction(this, presentation.getDisplayName(true), tableLevel)); @@ -265,10 +306,10 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { @Nullable public OrderEntry getSelectedEntry() { if (myEntryTable.getSelectedRowCount() != 1) return null; - return myModel.getItemAt(myEntryTable.getSelectedRow()).getEntry(); + return getItemAt(myEntryTable.getSelectedRow()).getEntry(); } - private void setFixedColumnWidth(final int columnIndex, final String textToMeasure) { + private void setFixedColumnWidth(final int columnIndex) { final TableColumn column = myEntryTable.getTableHeader().getColumnModel().getColumn(columnIndex); column.setResizable(false); column.setMaxWidth(column.getPreferredWidth()); @@ -289,7 +330,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { rootConfigurable.select((LibraryOrderEntry)entry, true); } else { - myEditButton.actionPerformed(null); + doEdit(); } } else if (entry instanceof JdkOrderEntry) { @@ -335,6 +376,17 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { }); final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myEntryTable); + AnActionButtonUpdater moveUpDownUpdater = new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + for (RowSorter.SortKey key : myEntryTable.getRowSorter().getSortKeys()) { + if (key.getSortOrder() != SortOrder.UNSORTED) { + return false; + } + } + return true; + } + }; decorator.setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { @@ -390,12 +442,16 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { moveSelectedRows(-1); } }) + .setMoveUpActionUpdater(moveUpDownUpdater) + .setMoveUpActionName("Move Up (disabled if items are shown in sorted order)") .setMoveDownAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { moveSelectedRows(+1); } }) + .setMoveDownActionUpdater(moveUpDownUpdater) + .setMoveDownActionName("Move Down (disabled if items are shown in sorted order)") .addExtraAction(myEditButton); if (isAnalyzeShown) { decorator.addExtraAction(analyzeButton); @@ -440,7 +496,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { for (final int selectedRow : selectedRows) { minRow = Math.min(minRow, selectedRow); maxRow = Math.max(maxRow, selectedRow); - final ClasspathTableItem item = myModel.getItemAt(selectedRow); + final ClasspathTableItem item = getItemAt(selectedRow); if (!item.isRemovable()) { removeButtonEnabled = false; } @@ -448,7 +504,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { if (myRemoveButton != null) { myRemoveButton.setEnabled(removeButtonEnabled && selectedRows.length > 0); } - ClasspathTableItem selectedItem = selectedRows.length == 1 ? myModel.getItemAt(selectedRows[0]) : null; + ClasspathTableItem selectedItem = selectedRows.length == 1 ? getItemAt(selectedRows[0]) : null; myEditButton.setEnabled(selectedItem != null && selectedItem.isEditable()); } @@ -504,11 +560,13 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { @Override public void addItems(List> toAdd) { for (ClasspathTableItem item : toAdd) { - myModel.addItem(item); + myModel.addRow(item); } - myModel.fireTableDataChanged(); - final ListSelectionModel selectionModel = myEntryTable.getSelectionModel(); - selectionModel.setSelectionInterval(myModel.getRowCount() - toAdd.size(), myModel.getRowCount() - 1); + TIntArrayList toSelect = new TIntArrayList(); + for (int i = myModel.getRowCount() - toAdd.size(); i < myModel.getRowCount(); i++) { + toSelect.add(myEntryTable.convertRowIndexToView(i)); + } + TableUtil.selectRows(myEntryTable, toSelect.toNativeArray()); TableUtil.scrollSelectionToVisible(myEntryTable); final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(myState.getProject()).getContext(); @@ -575,33 +633,31 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { } private void moveSelectedRows(int increment) { - if (increment == 0) { - return; - } - if (myEntryTable.isEditing()){ + LOG.assertTrue(increment == -1 || increment == 1); + if (myEntryTable.isEditing()) { myEntryTable.getCellEditor().stopCellEditing(); } final ListSelectionModel selectionModel = myEntryTable.getSelectionModel(); - for(int row = increment < 0? 0 : myModel.getRowCount() - 1; increment < 0? row < myModel.getRowCount() : row >= 0; row += - increment < 0? +1 : -1){ + for (int row = increment < 0 ? 0 : myModel.getRowCount() - 1; increment < 0 ? row < myModel.getRowCount() : row >= 0; row += + increment < 0 ? +1 : -1) { if (selectionModel.isSelectedIndex(row)) { final int newRow = moveRow(row, increment); selectionModel.removeSelectionInterval(row, row); selectionModel.addSelectionInterval(newRow, newRow); } } + List entries = getEntries(); + myState.getRootModel().rearrangeOrderEntries(entries.toArray(new OrderEntry[entries.size()])); + myModel.fireTableRowsUpdated(0, myModel.getRowCount() - 1); Rectangle cellRect = myEntryTable.getCellRect(selectionModel.getMinSelectionIndex(), 0, true); - if (cellRect != null) { - myEntryTable.scrollRectToVisible(cellRect); - } + myEntryTable.scrollRectToVisible(cellRect); myEntryTable.repaint(); - myListeners.getMulticaster().entryMoved(); } public void selectOrderEntry(@NotNull OrderEntry entry) { for (int row = 0; row < myModel.getRowCount(); row++) { - final OrderEntry orderEntry = myModel.getItemAt(row).getEntry(); + final OrderEntry orderEntry = getItemAt(row).getEntry(); if (orderEntry != null && entry.getPresentableName().equals(orderEntry.getPresentableName())) { myEntryTable.getSelectionModel().setSelectionInterval(row, row); TableUtil.scrollSelectionToVisible(myEntryTable); @@ -612,8 +668,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { private int moveRow(final int row, final int increment) { int newIndex = Math.abs(row + increment) % myModel.getRowCount(); - final ClasspathTableItem item = myModel.removeDataRow(row); - myModel.addItemAt(item, newIndex); + myModel.exchangeRows(row, newIndex); return newIndex; } @@ -625,7 +680,7 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { final int count = myModel.getRowCount(); final List entries = new ArrayList(count); for (int row = 0; row < count; row++) { - final OrderEntry entry = myModel.getItemAt(row).getEntry(); + final OrderEntry entry = myModel.getItem(row).getEntry(); if (entry != null) { entries.add(entry); } @@ -641,16 +696,25 @@ public class ClasspathPanelImpl extends JPanel implements ClasspathPanel { } public void forceInitFromModel() { - final int[] selection = myEntryTable.getSelectedRows(); + Set> oldSelection = new HashSet>(); + for (int i : myEntryTable.getSelectedRows()) { + ContainerUtil.addIfNotNull(getItemAt(i), oldSelection); + } myModel.clear(); myModel.init(); myModel.fireTableDataChanged(); - TableUtil.selectRows(myEntryTable, selection); + TIntArrayList newSelection = new TIntArrayList(); + for (int i = 0; i < myModel.getRowCount(); i++) { + if (oldSelection.contains(getItemAt(i))) { + newSelection.add(i); + } + } + TableUtil.selectRows(myEntryTable, newSelection.toNativeArray()); } - private static CellAppearanceEx getCellAppearance(final ClasspathTableItem item, - final StructureConfigurableContext context, - final boolean selected) { + static CellAppearanceEx getCellAppearance(final ClasspathTableItem item, + final StructureConfigurableContext context, + final boolean selected) { final OrderEntryAppearanceService service = OrderEntryAppearanceService.getInstance(); if (item instanceof InvalidJdkItem) { return service.forJdk(null, false, selected, true); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableItem.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableItem.java index f11e2295eaec..10bd32a9d1c0 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableItem.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableItem.java @@ -17,6 +17,7 @@ package com.intellij.openapi.roots.ui.configuration.classpath; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; +import com.intellij.openapi.util.Comparing; import org.jetbrains.annotations.Nullable; /** @@ -95,4 +96,17 @@ class ClasspathTableItem { return null; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ClasspathTableItem item = (ClasspathTableItem)o; + return Comparing.equal(myEntry, item.myEntry); + } + + @Override + public int hashCode() { + return myEntry != null ? myEntry.hashCode() : 0; + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableModel.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableModel.java index 8ffb161f488e..0be7e2def702 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableModel.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathTableModel.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi.roots.ui.configuration.classpath; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.roots.DependencyScope; import com.intellij.openapi.roots.JdkOrderEntry; @@ -23,32 +22,105 @@ import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; +import com.intellij.openapi.util.Comparing; +import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ItemRemovable; +import com.intellij.util.ui.ListTableModel; +import org.jetbrains.annotations.Nullable; -import javax.swing.table.AbstractTableModel; +import javax.swing.*; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; /** * @author nik */ -class ClasspathTableModel extends AbstractTableModel implements ItemRemovable { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.classpath.ClasspathTableModel"); - public static final String EXPORT_COLUMN_NAME = ProjectBundle.message("modules.order.export.export.column"); +class ClasspathTableModel extends ListTableModel> implements ItemRemovable { + private static final String EXPORT_COLUMN_NAME = ProjectBundle.message("modules.order.export.export.column"); + private static final ColumnInfo, Boolean> EXPORT_COLUMN_INFO = new ColumnInfo, Boolean>(EXPORT_COLUMN_NAME) { + @Nullable + @Override + public Boolean valueOf(ClasspathTableItem item) { + return item.isExported(); + } + + @Override + public void setValue(ClasspathTableItem item, Boolean value) { + item.setExported(value); + } + + @Override + public boolean isCellEditable(ClasspathTableItem item) { + return item.isExportable(); + } + + @Override + public Class getColumnClass() { + return Boolean.class; + } + }; private static final String SCOPE_COLUMN_NAME = ProjectBundle.message("modules.order.export.scope.column"); + private static final Comparator DEPENDENCY_SCOPE_COMPARATOR = new Comparator() { + @Override + public int compare(DependencyScope o1, DependencyScope o2) { + return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName()); + } + }; + private static final Comparator> CLASSPATH_ITEM_SCOPE_COMPARATOR = + new Comparator>() { + @Override + public int compare(ClasspathTableItem o1, ClasspathTableItem o2) { + return Comparing.compare(o1.getScope(), o2.getScope(), DEPENDENCY_SCOPE_COMPARATOR); + } + }; + private static final ColumnInfo, DependencyScope> SCOPE_COLUMN_INFO = new ColumnInfo, DependencyScope>(SCOPE_COLUMN_NAME) { + @Nullable + @Override + public DependencyScope valueOf(ClasspathTableItem item) { + return item.getScope(); + } + + @Override + public void setValue(ClasspathTableItem item, DependencyScope value) { + item.setScope(value); + } + + @Override + public boolean isCellEditable(ClasspathTableItem item) { + return item.isExportable(); + } + + @Override + public Class getColumnClass() { + return DependencyScope.class; + } + + @Nullable + @Override + public Comparator> getComparator() { + return CLASSPATH_ITEM_SCOPE_COMPARATOR; + } + }; public static final int EXPORT_COLUMN = 0; public static final int ITEM_COLUMN = 1; public static final int SCOPE_COLUMN = 2; - private final List> myItems = new ArrayList>(); private final ModuleConfigurationState myState; private StructureConfigurableContext myContext; public ClasspathTableModel(final ModuleConfigurationState state, StructureConfigurableContext context) { + super(EXPORT_COLUMN_INFO, new ClasspathTableItemClasspathColumnInfo(context), SCOPE_COLUMN_INFO); myState = state; myContext = context; init(); } + @Override + public RowSorter.SortKey getDefaultSortKey() { + return new RowSorter.SortKey(1, SortOrder.UNSORTED); + } + private ModifiableRootModel getModel() { return myState.getRootModel(); } @@ -56,111 +128,58 @@ class ClasspathTableModel extends AbstractTableModel implements ItemRemovable { public void init() { final OrderEntry[] orderEntries = getModel().getOrderEntries(); boolean hasJdkOrderEntry = false; + List> items = new ArrayList>(); for (final OrderEntry orderEntry : orderEntries) { if (orderEntry instanceof JdkOrderEntry) { hasJdkOrderEntry = true; } - addItem(ClasspathTableItem.createItem(orderEntry, myContext)); + items.add(ClasspathTableItem.createItem(orderEntry, myContext)); } if (!hasJdkOrderEntry) { - addItemAt(new InvalidJdkItem(), 0); + items.add(0, new InvalidJdkItem()); } - } - - public ClasspathTableItem getItemAt(int row) { - return myItems.get(row); - } - - public void addItem(ClasspathTableItem item) { - myItems.add(item); - } - - public void addItemAt(ClasspathTableItem item, int row) { - myItems.add(row, item); - } - - public ClasspathTableItem removeDataRow(int row) { - return myItems.remove(row); - } - - - @Override - public void removeRow(int row) { - removeDataRow(row); + setItems(items); } public void clear() { - myItems.clear(); + setItems(Collections.>emptyList()); } - @Override - public int getRowCount() { - return myItems.size(); - } + private static class ClasspathTableItemClasspathColumnInfo extends ColumnInfo, ClasspathTableItem> { + private final Comparator> myItemComparator; - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - final ClasspathTableItem item = myItems.get(rowIndex); - if (columnIndex == EXPORT_COLUMN) { - return item.isExported(); + public ClasspathTableItemClasspathColumnInfo(final StructureConfigurableContext context) { + super(""); + myItemComparator = new Comparator>() { + @Override + public int compare(ClasspathTableItem o1, ClasspathTableItem o2) { + String text1 = ClasspathPanelImpl.getCellAppearance(o1, context, false).getText(); + String text2 = ClasspathPanelImpl.getCellAppearance(o2, context, false).getText(); + return text1.compareToIgnoreCase(text2); + } + }; } - if (columnIndex == SCOPE_COLUMN) { - return item.getScope(); + + @Nullable + @Override + public Comparator> getComparator() { + return myItemComparator; } - if (columnIndex == ITEM_COLUMN) { + + @Nullable + @Override + public ClasspathTableItem valueOf(ClasspathTableItem item) { return item; } - LOG.error("Incorrect column index: " + columnIndex); - return null; - } - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - final ClasspathTableItem item = myItems.get(rowIndex); - if (columnIndex == EXPORT_COLUMN) { - item.setExported(((Boolean)aValue).booleanValue()); + @Override + public boolean isCellEditable(ClasspathTableItem item) { + return false; } - else if (columnIndex == SCOPE_COLUMN && aValue instanceof DependencyScope) { - item.setScope((DependencyScope) aValue); - } - } - @Override - public String getColumnName(int column) { - if (column == EXPORT_COLUMN) { - return EXPORT_COLUMN_NAME; - } - if (column == SCOPE_COLUMN) { - return SCOPE_COLUMN_NAME; - } - return ""; - } - - @Override - public Class getColumnClass(int column) { - if (column == EXPORT_COLUMN) { - return Boolean.class; - } - if (column == SCOPE_COLUMN) { - return DependencyScope.class; - } - if (column == ITEM_COLUMN) { + @Override + public Class getColumnClass() { return ClasspathTableItem.class; } - return super.getColumnClass(column); - } - - @Override - public int getColumnCount() { - return 3; - } - - @Override - public boolean isCellEditable(int row, int column) { - if (column == EXPORT_COLUMN || column == SCOPE_COLUMN) { - final ClasspathTableItem item = myItems.get(row); - return item != null && item.isExportable(); - } - return false; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java index af5f14e25131..c888ca9b9f04 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java @@ -544,7 +544,10 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM if (document != null) { final XmlTag rootTag = document.getRootTag(); final String externalName = getExternalName(listOwner, false); - if (rootTag != null) { + if (externalName == null) { + LOG.info("member without external name: " + listOwner); + } + if (rootTag != null && externalName != null) { XmlTag anchor = null; for (XmlTag item : rootTag.getSubTags()) { int compare = Comparing.compare(externalName, StringUtil.unescapeXml(item.getAttributeValue("name"))); @@ -573,10 +576,12 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM text += createAnnotationTag(annotationFQName, values); text += ""; rootTag.addAfter(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text), anchor); + commitChanges(xmlFile); + notifyAfterAnnotationChanging(listOwner, annotationFQName, true); + return; } } - commitChanges(xmlFile); - notifyAfterAnnotationChanging(listOwner, annotationFQName, true); + notifyAfterAnnotationChanging(listOwner, annotationFQName, false); } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java index bb45d770dea1..ab86b701c3fc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java @@ -382,6 +382,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor { for (final PsiField field : psiClass.getFields()) { if (field == element) continue; + if (StringUtil.isEmpty(field.getName())) continue; PsiUtilCore.ensureValid(field); PsiType fieldType = field.getType(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnonymousClassElementBase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnonymousClassElementBase.java index c52bf6f41214..161c80c92466 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnonymousClassElementBase.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnonymousClassElementBase.java @@ -85,6 +85,9 @@ public abstract class AnonymousClassElementBase extends ClassElement { else if (i == JavaTokenType.RBRACE) { return getChildRole(child, ChildRole.RBRACE); } + else if (i == JavaTokenType.COMMA) { + return ChildRole.COMMA; + } else { return ChildRoleBase.NONE; } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java index 2c2d8b2e1256..cbfff3ed3534 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java @@ -323,7 +323,12 @@ public class PsiScopesUtil { if (refMethods.length > 0) { final PsiClass baseClass = PsiUtil.resolveClassInType(type); if (baseClass != null && !hasCovariantOverriding(baseClass, refMethods)) { - type = initializer.getType(); + for (PsiMethod method : refMethods) { + if (method.findSuperMethods(baseClass).length > 0) { + type = initializer.getType(); + break; + } + } } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/HiddenMethodsOfAnonymousClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/HiddenMethodsOfAnonymousClass.java new file mode 100644 index 000000000000..f1ecb50a5662 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/HiddenMethodsOfAnonymousClass.java @@ -0,0 +1,9 @@ +class Example { + public static void main(String[] args) { + final Runnable r = new Runnable() { + public void run() {} + public void m2() {} + }; + r.m2(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA130129.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA130129.java new file mode 100644 index 000000000000..8f933f79e7c7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA130129.java @@ -0,0 +1,72 @@ +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +class Test +{ + public static class WrapperBase + { + public T unwrap(E edge) + { + //noinspection unchecked + return (T)((DefaultEdge)edge).getSource(); + } + } + + public static class Wrapper extends WrapperBase + { + } + + public static class DefaultEdge + { + private final TaskId taskId; + + public DefaultEdge(TaskId taskId) + { + this.taskId = taskId; + } + + public Object getSource() + { + return taskId; + } + } + + public static class TaskId + { + private final String id; + + public TaskId(String id) + { + this.id = id; + } + + public String getId() + { + return id; + } + + @Override + public String toString() + { + return getId(); + } + } + + public static void main(String[] args) + { + Wrapper w = new Wrapper<>(); + Set s = new HashSet<>(); + s.add(new DefaultEdge(new TaskId("1"))); + s.add(new DefaultEdge(new TaskId("2"))); + s.add(new DefaultEdge(new TaskId("3"))); + + Set processed = s + .stream() + .map(w::unwrap) + .filter(edge -> !edge.getId().equals("")) + .collect(Collectors.toSet()); + + System.out.println(processed); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index ac57a71e9c9f..fde013dca76d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -380,6 +380,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { //jdk should propagate LL 1.4 but actually it provides LL 1.7?! public void testCastObjectToIntJdk14() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_4, false); } + public void testHiddenMethodsOfAnonymousClass() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 998ecff12a7c..d6153e6b3d84 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -22,8 +22,6 @@ import com.intellij.idea.Bombed; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.testFramework.IdeaTestUtil; -import junit.framework.Test; -import junit.framework.TestSuite; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -141,6 +139,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIDEA130129() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy index 9c378a1e50cf..0a5b65deb372 100644 --- a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy +++ b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy @@ -247,10 +247,12 @@ class Intf { List elements = ['empty'] def semaphore = new Semaphore() semaphore.down() - popup.scheduleCalcElements(text, checkboxState, ModalityState.NON_MODAL, { set -> - elements = set as List - semaphore.up() - } as Consumer>) + edt { + popup.scheduleCalcElements(text, checkboxState, ModalityState.NON_MODAL, { set -> + elements = set as List + semaphore.up() + } as Consumer>) + } if (!semaphore.waitFor(10000)) { printThreadDump() fail() diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java index c01395b66869..0debdda7b434 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java @@ -579,4 +579,14 @@ public class JavaFormatterSpaceTest extends AbstractJavaFormatterTest { doMethodTest(before, "Test.class"); } + public void testMultipleFieldDeclaration_InAnonymousClass() { + doMethodTest( + "new Object() {\n" + + "boolean one, two;\n" + + "};", + "new Object() {\n" + + " boolean one, two;\n" + + "};" + ); + } } diff --git a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java index e5a9ee47daed..78c840ad2e65 100644 --- a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java +++ b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java @@ -2,23 +2,30 @@ package com.intellij.compiler; import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration; import com.intellij.compiler.server.BuildManager; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.application.impl.ApplicationImpl; +import com.intellij.openapi.components.ExportableApplicationComponent; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.impl.stores.StateStorageManager; import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; -import com.intellij.openapi.projectRoots.impl.ProjectJdkTableImpl; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.NamedJDOMExternalizable; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -28,7 +35,6 @@ import org.jdom.Element; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions; import org.jetbrains.jps.model.serialization.JDomSerializationUtil; -import org.jetbrains.jps.model.serialization.JpsGlobalLoader; import java.io.File; import java.io.IOException; @@ -59,28 +65,47 @@ public class CompilerTestUtil { } public static void saveApplicationSettings() { - try { - ProjectJdkTableImpl table = (ProjectJdkTableImpl)ProjectJdkTable.getInstance(); - Element root = new Element("application"); - root.addContent(JDomSerializationUtil.createComponentElement(JpsGlobalLoader.SDK_TABLE_COMPONENT_NAME).addContent(table.getState().cloneContent())); - saveApplicationComponent(root, ((ProjectJdkTableImpl)ProjectJdkTable.getInstance()).getExportFiles()[0]); + saveApplicationComponent(ProjectJdkTable.getInstance()); + saveApplicationComponent(FileTypeManager.getInstance()); + } - FileTypeManagerImpl fileTypeManager = (FileTypeManagerImpl)FileTypeManager.getInstance(); - Element fileTypesComponent = JDomSerializationUtil.createComponentElement(fileTypeManager.getComponentName()); - fileTypeManager.writeExternal(fileTypesComponent); - saveApplicationComponent(new Element("application").addContent(fileTypesComponent), PathManager.getOptionsFile(fileTypeManager)); - } - catch (IOException e) { - throw new RuntimeException(e); + public static void saveApplicationComponent(Object appComponent) { + try { + final File file; + String componentName; + State state = appComponent.getClass().getAnnotation(State.class); + if (state != null) { + componentName = state.name(); + Storage lastStorage = state.storages()[state.storages().length - 1]; + StateStorageManager storageManager = ((ApplicationImpl)ApplicationManager.getApplication()).getStateStore().getStateStorageManager(); + file = new File(storageManager.expandMacros(lastStorage.file())); + } + else if (appComponent instanceof ExportableApplicationComponent && appComponent instanceof NamedJDOMExternalizable) { + componentName = ((ExportableApplicationComponent)appComponent).getComponentName(); + file = PathManager.getOptionsFile((NamedJDOMExternalizable)appComponent); + } + else { + throw new AssertionError( appComponent.getClass() + " doesn't have @State annotation and doesn't implement ExportableApplicationComponent"); + } + + Element root = new Element("application"); + Element element = JDomSerializationUtil.createComponentElement(componentName); + if (appComponent instanceof JDOMExternalizable) { + ((JDOMExternalizable)appComponent).writeExternal(element); + } + else { + element.addContent(((PersistentStateComponent)appComponent).getState().cloneContent()); + } + root.addContent(element); + FileUtil.createParentDirs(file); + JDOMUtil.writeDocument(new Document(root), file, SystemProperties.getLineSeparator()); } catch (WriteExternalException e) { throw new RuntimeException(e); } - } - - private static void saveApplicationComponent(Element root, final File file) throws IOException { - FileUtil.createParentDirs(file); - JDOMUtil.writeDocument(new Document(root), file, SystemProperties.getLineSeparator()); + catch (IOException e) { + throw new RuntimeException(e); + } } public static void enableExternalCompiler() { diff --git a/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java b/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java index 712a4cdedb88..4ecf87470467 100644 --- a/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java +++ b/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java @@ -37,7 +37,7 @@ public class JsonCodeStyleSettingsProvider extends CodeStyleSettingsProvider { @Nullable @Override public String getHelpTopic() { - return null; + return "reference.settingsdialog.codestyle.json"; } }; } diff --git a/json/tests/testData/psi/IncompleteObjectProperties.txt b/json/tests/testData/psi/IncompleteObjectProperties.txt index 4187382bfd1e..62b4a2188e72 100644 --- a/json/tests/testData/psi/IncompleteObjectProperties.txt +++ b/json/tests/testData/psi/IncompleteObjectProperties.txt @@ -14,14 +14,14 @@ JsonFile: IncompleteObjectProperties.json JsonProperty JsonStringLiteral PsiElement(DOUBLE_QUOTED_STRING)('"bar"') - PsiErrorElement:':' expected, got ',' - + PsiErrorElement:':' expected, got ',' + PsiElement(,)(',') PsiWhiteSpace('\n ') JsonProperty JsonStringLiteral PsiElement(DOUBLE_QUOTED_STRING)('"baz"') - PsiErrorElement:':' expected, got '}' - + PsiErrorElement:':' expected, got '}' + PsiWhiteSpace('\n') PsiElement(})('}') \ No newline at end of file diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java index db0c71b9f99a..d383ffb31466 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/FilePatternPackageSet.java @@ -33,6 +33,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import java.util.regex.Pattern; @@ -56,12 +57,12 @@ public class FilePatternPackageSet extends PatternBasedPackageSet { if (modulePattern.startsWith("group:")) { int idx = modulePattern.indexOf(':', 6); if (idx == -1) idx = modulePattern.length(); - myModuleGroupPattern = Pattern.compile(StringUtil.escapeToRegexp(modulePattern.substring(6, idx))); + myModuleGroupPattern = Pattern.compile(StringUtil.replace(escapeToRegexp(modulePattern.substring(6, idx)), "*", ".*")); if (idx < modulePattern.length() - 1) { - myModulePattern = Pattern.compile(StringUtil.escapeToRegexp(modulePattern.substring(idx + 1))); + myModulePattern = Pattern.compile(StringUtil.replace(escapeToRegexp(modulePattern.substring(idx + 1)), "*", ".*")); } } else { - myModulePattern = Pattern.compile(StringUtil.escapeToRegexp(modulePattern)); + myModulePattern = Pattern.compile(StringUtil.replace(escapeToRegexp(modulePattern), "*", ".*")); } } myFilePattern = filePattern != null ? Pattern.compile(convertToRegexp(filePattern, '/')) : null; @@ -109,10 +110,25 @@ public class FilePatternPackageSet extends PatternBasedPackageSet { return modulePattern == null && moduleGroupPattern == null; } + @NotNull + private static String escapeToRegexp(@NotNull CharSequence text) { + StringBuilder builder = new StringBuilder(text.length()); + for (int i = 0; i < text.length(); i++) { + final char c = text.charAt(i); + if (c == ' ' || Character.isLetter(c) || Character.isDigit(c) || c == '_' || c == '*') { + builder.append(c); + } + else { + builder.append('\\').append(c); + } + } - //public for tests only + return builder.toString(); + } + + @TestOnly public static String convertToRegexp(String aspectsntx, char separator) { - StringBuffer buf = new StringBuffer(aspectsntx.length()); + StringBuilder buf = new StringBuilder(aspectsntx.length()); int cur = 0; boolean isAfterSeparator = false; boolean isAfterAsterix = false; diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index b95ed788cbb1..c434ff41fd2c 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -320,8 +320,9 @@ public class PushController implements Disposable { node.stopLoading(); if (shouldBeSelected) { // never remove selection; initially all checkboxes are not selected node.setChecked(true); + model.setSelected(true); } - node.fireOnSelectionChange(shouldBeSelected); + myDialog.updateButtons(); } }); } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java index d875103c29d6..78a90f21992a 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java @@ -31,8 +31,8 @@ import com.intellij.ui.CheckedTreeNode; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.tree.TreeUtil; -import com.intellij.vcs.log.VcsFullCommitDetails; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -44,10 +44,8 @@ import javax.swing.tree.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EventObject; +import java.util.*; +import java.util.List; public class PushLog extends JPanel implements TypeSafeDataProvider { @@ -167,40 +165,63 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { } private void updateChangesView() { - TreePath[] nodes = myTree.getSelectionPaths(); - if (nodes != null) { - ArrayList changes = new ArrayList(); - for (TreePath path : nodes) { - if (path.getLastPathComponent() instanceof CommitNode) { - CommitNode commitDetailsNode = (CommitNode)path.getLastPathComponent(); - changes.addAll(commitDetailsNode.getUserObject().getChanges()); - } - else if (path.getLastPathComponent() instanceof RepositoryNode) { - changes.addAll(collectAllChanges((RepositoryNode)path.getLastPathComponent())); - } - } + int[] rows = myTree.getSelectionRows(); + if (rows.length != 0) { myChangesBrowser.getViewer().setEmptyText("No differences"); - myChangesBrowser.setChangesToDisplay(CommittedChangesTreeBrowser.zipChanges(changes)); - return; + myChangesBrowser.setChangesToDisplay(collectAllChanges(rows)); + } + else { + setDefaultEmptyText(); + myChangesBrowser.setChangesToDisplay(Collections.emptyList()); } - setDefaultEmptyText(); - myChangesBrowser.setChangesToDisplay(Collections.emptyList()); } @NotNull - private static Collection collectAllChanges(@NotNull RepositoryNode rootNode) { - ArrayList changes = new ArrayList(); - if (rootNode.getChildCount() <= 0) return changes; - for (DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)rootNode.getFirstChild(); - childNode != null; - childNode = (DefaultMutableTreeNode)rootNode.getChildAfter(childNode)) { - if (childNode instanceof CommitNode) { - changes.addAll(((CommitNode)childNode).getUserObject().getChanges()); + private List collectAllChanges(@NotNull int[] selectedRows) { + List selectedNodes = getNodesForRows(getSortedRows(selectedRows)); + List commitNodes = collectSelectedCommitNodes(selectedNodes); + return CommittedChangesTreeBrowser.zipChanges(collectChanges(commitNodes)); + } + + @NotNull + private static List collectSelectedCommitNodes(@NotNull List selectedNodes) { + List nodes = ContainerUtil.newArrayList(); + for (DefaultMutableTreeNode node : selectedNodes) { + if (node instanceof RepositoryNode) { + nodes.addAll(getChildNodes((RepositoryNode)node)); + } + else if (node instanceof CommitNode && !nodes.contains(node)) { + nodes.add((CommitNode)node); } } + return nodes; + } + + @NotNull + private static List collectChanges(@NotNull List commitNodes) { + List changes = ContainerUtil.newArrayList(); + for (CommitNode node : commitNodes) { + changes.addAll(node.getUserObject().getChanges()); + } return changes; } + @NotNull + private static List getChildNodes(@NotNull RepositoryNode node) { + List nodes = ContainerUtil.newArrayList(); + if (node.getChildCount() < 1) { + return nodes; + } + for (DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)node.getFirstChild(); + childNode != null; + childNode = (DefaultMutableTreeNode)node.getChildAfter(childNode)) { + if (childNode instanceof CommitNode) { + nodes.add(0, (CommitNode)childNode); + } + } + return nodes; + } + private void setDefaultEmptyText() { myChangesBrowser.getViewer().setEmptyText("No commits selected"); } @@ -209,27 +230,37 @@ public class PushLog extends JPanel implements TypeSafeDataProvider { @Override public void calcData(DataKey key, DataSink sink) { if (VcsDataKeys.CHANGES.equals(key)) { - DefaultMutableTreeNode[] selectedNodes = myTree.getSelectedNodes(DefaultMutableTreeNode.class, null); - if (selectedNodes.length == 0) { - return; - } - DefaultMutableTreeNode node = selectedNodes[0]; - Object object = node.getUserObject(); - - Collection changes = null; - if (object instanceof VcsFullCommitDetails) { - changes = ((VcsFullCommitDetails)object).getChanges(); - } - else if (node instanceof RepositoryNode) { - changes = collectAllChanges((RepositoryNode)node); - } - - if (changes != null) { + int[] rows = myTree.getSelectionRows(); + if (rows.length != 0) { + Collection changes = collectAllChanges(rows); sink.put(key, ArrayUtil.toObjectArray(changes, Change.class)); } } } + @NotNull + private static List getSortedRows(@NotNull int[] rows) { + List sorted = ContainerUtil.newArrayList(); + for (int row : rows) { + sorted.add(row); + } + Collections.sort(sorted, Collections.reverseOrder()); + return sorted; + } + + @NotNull + private List getNodesForRows(@NotNull List rows) { + List nodes = ContainerUtil.newArrayList(); + for (Integer row : rows) { + TreePath path = myTree.getPathForRow(row); + Object pathComponent = path == null ? null : path.getLastPathComponent(); + if (pathComponent instanceof DefaultMutableTreeNode) { + nodes.add((DefaultMutableTreeNode)pathComponent); + } + } + return nodes; + } + @Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { if (e.getKeyCode() == KeyEvent.VK_ENTER && e.getModifiers() == 0 && pressed) { diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java index b75ce5079558..29a021113887 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java @@ -35,7 +35,7 @@ import java.util.concurrent.atomic.AtomicReference; public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode, Comparable { @NotNull protected final LoadingIcon myLoadingIcon; - @NotNull protected final AtomicBoolean myLoading = new AtomicBoolean(true); + @NotNull protected final AtomicBoolean myLoading = new AtomicBoolean(); @NotNull private final RepositoryWithBranchPanel myRepositoryPanel; @Nullable private Future> myFuture; diff --git a/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java b/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java index fb782db28cd4..5bdf700b4387 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java +++ b/platform/lang-api/src/com/intellij/execution/filters/CompositeFilter.java @@ -187,4 +187,8 @@ public class CompositeFilter implements Filter, FilterMixin { this.forceUseAllFilters = forceUseAllFilters; } + @Override + public String toString() { + return "CompositeFilter: " + myFilters; + } } diff --git a/platform/lang-api/src/com/intellij/psi/PsiElementRef.java b/platform/lang-api/src/com/intellij/psi/PsiElementRef.java index dd1044582297..5988ec808437 100644 --- a/platform/lang-api/src/com/intellij/psi/PsiElementRef.java +++ b/platform/lang-api/src/com/intellij/psi/PsiElementRef.java @@ -16,6 +16,7 @@ package com.intellij.psi; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -94,7 +95,7 @@ public final class PsiElementRef { private final T myElement; public Real(@NotNull T element) { - LOG.assertTrue(element.isValid()); + PsiUtilCore.ensureValid(element); myElement = element; } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AbstractArrangementRuleAction.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AbstractArrangementRuleAction.java index 1e5a84da3f8d..ec700f7e2363 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AbstractArrangementRuleAction.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/action/AbstractArrangementRuleAction.java @@ -35,17 +35,6 @@ public abstract class AbstractArrangementRuleAction extends AnAction { } protected void scrollRowToVisible(@NotNull ArrangementMatchingRulesControl control, int row) { - final Rectangle rect = control.getCellRect(row, 0, false); - if (row != control.getEditingRow() - 1) { - control.scrollRectToVisible(rect); - } - else { - final Rectangle editorRect = control.getCellRect(row + 1, 0, false); - if(!rect.isEmpty() && !editorRect.isEmpty()) { - final int height = (int)(rect.getHeight() + editorRect.getHeight()); - final Rectangle visibleRect = new Rectangle((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), height); - control.scrollRectToVisible(visibleRect); - } - } + control.scrollRowToVisible(row); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java index 5889df54e1b1..6f5963fb4dac 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java @@ -329,6 +329,21 @@ public class ArrangementMatchingRulesControl extends JBTable { showEditor(myEditor, rowToEdit); } + public void scrollRowToVisible(int row) { + final Rectangle rect = getCellRect(row, 0, false); + if (row != getEditingRow() - 1) { + scrollRectToVisible(rect); + } + else { + final Rectangle editorRect = getCellRect(row + 1, 0, false); + if(!rect.isEmpty() && !editorRect.isEmpty()) { + final int height = (int)(rect.getHeight() + editorRect.getHeight()); + final Rectangle visibleRect = new Rectangle((int)rect.getX(), (int)rect.getY(), (int)rect.getWidth(), height); + scrollRectToVisible(visibleRect); + } + } + } + public void showEditor(@NotNull ArrangementMatchingRuleEditor editor, int rowToEdit) { if (myEditorRow == rowToEdit + 1) { return; diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java index fe36724293f4..5bbba9eb8a7c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/util/ArrangementListRowDecorator.java @@ -214,6 +214,7 @@ public class ArrangementListRowDecorator extends JPanel implements ArrangementUi int row = myControl.getRowByRenderer(this); if (row >= 0) { myControl.showEditor(row); + myControl.scrollRowToVisible(row); myBeingEdited = true; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index c5828145c991..99900deda597 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -115,17 +115,17 @@ public class DocumentationManager extends DockablePopupManager { @Override public String getFullName(final Object element) { - for(ChooseByNameContributor c: getContributors()) { + if (element instanceof PsiElement && !((PsiElement)element).isValid()) { + return null; + } + + for (ChooseByNameContributor c : getContributors()) { if (c instanceof GotoClassContributor) { - String result = ((GotoClassContributor) c).getQualifiedName((NavigationItem) element); + String result = ((GotoClassContributor)c).getQualifiedName((NavigationItem)element); if (result != null) return result; } } diff --git a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java index 267333399dbd..830b2697aa97 100644 --- a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java +++ b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java @@ -1,3 +1,19 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // This class is a runtime engine for parsers generated by Grammar-Kit. // Do not modify or refactor without complete investigation and/or review. package com.intellij.lang.parser; @@ -70,169 +86,174 @@ public class GeneratedParserUtilBase { } }; - public static boolean eof(PsiBuilder builder_, int level_) { - return builder_.eof(); + public static boolean eof(PsiBuilder builder, int level) { + return builder.eof(); } - public static int current_position_(PsiBuilder builder_) { - return builder_.rawTokenIndex(); + public static int current_position_(PsiBuilder builder) { + return builder.rawTokenIndex(); } - public static boolean recursion_guard_(PsiBuilder builder_, int level_, String funcName_) { - if (level_ > MAX_RECURSION_LEVEL) { - builder_.error("Maximum recursion level (" + MAX_RECURSION_LEVEL + ") reached in '" + funcName_ + "'"); + public static boolean recursion_guard_(PsiBuilder builder, int level, String funcName) { + if (level > MAX_RECURSION_LEVEL) { + builder.error("Maximum recursion level (" + MAX_RECURSION_LEVEL + ") reached in '" + funcName + "'"); return false; } return true; } - public static boolean empty_element_parsed_guard_(PsiBuilder builder_, String funcName_, int prev_position_) { - if (prev_position_ == current_position_(builder_)) { - builder_.error("Empty element parsed in '" + funcName_ + "' at offset " + builder_.getCurrentOffset()); + public static boolean empty_element_parsed_guard_(PsiBuilder builder, String funcName, int pos) { + if (pos == current_position_(builder)) { + builder.error("Empty element parsed in '" + funcName + "' at offset " + builder.getCurrentOffset()); return false; } return true; } - public static boolean invalid_left_marker_guard_(PsiBuilder builder_, PsiBuilder.Marker marker_, String funcName_) { - //builder_.error("Invalid left marker encountered in " + funcName_ +" at offset " + builder_.getCurrentOffset()); - boolean goodMarker = marker_ != null; // && ((LighterASTNode)marker_).getTokenType() != TokenType.ERROR_ELEMENT; + public static boolean invalid_left_marker_guard_(PsiBuilder builder, PsiBuilder.Marker marker, String funcName) { + //builder.error("Invalid left marker encountered in " + funcName_ +" at offset " + builder.getCurrentOffset()); + boolean goodMarker = marker != null; // && ((LighterASTNode)marker).getTokenType() != TokenType.ERROR_ELEMENT; if (!goodMarker) return false; - ErrorState state = ErrorState.get(builder_); + ErrorState state = ErrorState.get(builder); return !state.frameStack.isEmpty(); } - public static TokenSet create_token_set_(IElementType... tokenTypes_) { - return TokenSet.create(tokenTypes_); + public static TokenSet create_token_set_(IElementType... tokenTypes) { + return TokenSet.create(tokenTypes); } - private static boolean consumeTokens(PsiBuilder builder_, boolean smart, int pin, IElementType... tokens) { - ErrorState state = ErrorState.get(builder_); + public static boolean leftMarkerIs(PsiBuilder builder, IElementType type) { + LighterASTNode marker = builder.getLatestDoneMarker(); + return marker != null && marker.getTokenType() == type; + } + + private static boolean consumeTokens(PsiBuilder builder, boolean smart, int pin, IElementType... tokens) { + ErrorState state = ErrorState.get(builder); if (state.completionState != null && state.predicateCount == 0) { - addCompletionVariant(builder_, state.completionState, tokens); + addCompletionVariant(builder, state.completionState, tokens); } // suppress single token completion CompletionState completionState = state.completionState; state.completionState = null; - boolean result_ = true; - boolean pinned_ = false; + boolean result = true; + boolean pinned = false; for (int i = 0, tokensLength = tokens.length; i < tokensLength; i++) { - if (pin > 0 && i == pin) pinned_ = result_; - if (result_ || pinned_) { + if (pin > 0 && i == pin) pinned = result; + if (result || pinned) { boolean fast = smart && i == 0; - if (!(fast ? consumeTokenFast(builder_, tokens[i]) : consumeToken(builder_, tokens[i]))) { - result_ = false; - if (pin < 0 || pinned_) report_error_(builder_, state, false); + if (!(fast ? consumeTokenFast(builder, tokens[i]) : consumeToken(builder, tokens[i]))) { + result = false; + if (pin < 0 || pinned) report_error_(builder, state, false); } } } state.completionState = completionState; - return pinned_ || result_; + return pinned || result; } - public static boolean consumeTokens(PsiBuilder builder_, int pin_, IElementType... token) { - return consumeTokens(builder_, false, pin_, token); + public static boolean consumeTokens(PsiBuilder builder, int pin, IElementType... token) { + return consumeTokens(builder, false, pin, token); } - public static boolean consumeTokensSmart(PsiBuilder builder_, int pin_, IElementType... token) { - return consumeTokens(builder_, true, pin_, token); + public static boolean consumeTokensSmart(PsiBuilder builder, int pin, IElementType... token) { + return consumeTokens(builder, true, pin, token); } - public static boolean parseTokens(PsiBuilder builder_, int pin_, IElementType... tokens) { - return parseTokens(builder_, false, pin_, tokens); + public static boolean parseTokens(PsiBuilder builder, int pin, IElementType... tokens) { + return parseTokens(builder, false, pin, tokens); } - public static boolean parseTokensSmart(PsiBuilder builder_, int pin_, IElementType... tokens) { - return parseTokens(builder_, true, pin_, tokens); + public static boolean parseTokensSmart(PsiBuilder builder, int pin, IElementType... tokens) { + return parseTokens(builder, true, pin, tokens); } - public static boolean parseTokens(PsiBuilder builder_, boolean smart, int pin_, IElementType... tokens) { - PsiBuilder.Marker marker_ = builder_.mark(); - boolean result_ = consumeTokens(builder_, smart, pin_, tokens); - if (!result_) { - marker_.rollbackTo(); + public static boolean parseTokens(PsiBuilder builder, boolean smart, int pin, IElementType... tokens) { + PsiBuilder.Marker marker = builder.mark(); + boolean result = consumeTokens(builder, smart, pin, tokens); + if (!result) { + marker.rollbackTo(); } else { - marker_.drop(); + marker.drop(); } - return result_; + return result; } - public static boolean consumeTokenSmart(PsiBuilder builder_, IElementType token) { - addCompletionVariantSmart(builder_, token); - return consumeTokenFast(builder_, token); + public static boolean consumeTokenSmart(PsiBuilder builder, IElementType token) { + addCompletionVariantSmart(builder, token); + return consumeTokenFast(builder, token); } - public static boolean consumeTokenSmart(PsiBuilder builder_, String token) { - addCompletionVariantSmart(builder_, token); - return consumeTokenFast(builder_, token); + public static boolean consumeTokenSmart(PsiBuilder builder, String token) { + addCompletionVariantSmart(builder, token); + return consumeTokenFast(builder, token); } - public static boolean consumeToken(PsiBuilder builder_, IElementType token) { - addVariantSmart(builder_, token, true); - if (nextTokenIsFast(builder_, token)) { - builder_.advanceLexer(); + public static boolean consumeToken(PsiBuilder builder, IElementType token) { + addVariantSmart(builder, token, true); + if (nextTokenIsFast(builder, token)) { + builder.advanceLexer(); return true; } return false; } - public static boolean consumeTokenFast(PsiBuilder builder_, IElementType token) { - if (nextTokenIsFast(builder_, token)) { - builder_.advanceLexer(); + public static boolean consumeTokenFast(PsiBuilder builder, IElementType token) { + if (nextTokenIsFast(builder, token)) { + builder.advanceLexer(); return true; } return false; } - public static boolean consumeToken(PsiBuilder builder_, String text) { - return consumeToken(builder_, text, ErrorState.get(builder_).caseSensitive); + public static boolean consumeToken(PsiBuilder builder, String text) { + return consumeToken(builder, text, ErrorState.get(builder).caseSensitive); } - public static boolean consumeToken(PsiBuilder builder_, String text, boolean caseSensitive) { - addVariantSmart(builder_, text, true); - int count = nextTokenIsFast(builder_, text, caseSensitive); + public static boolean consumeToken(PsiBuilder builder, String text, boolean caseSensitive) { + addVariantSmart(builder, text, true); + int count = nextTokenIsFast(builder, text, caseSensitive); if (count > 0) { - while (count-- > 0) builder_.advanceLexer(); + while (count-- > 0) builder.advanceLexer(); return true; } return false; } - public static boolean consumeTokenFast(PsiBuilder builder_, String text) { - int count = nextTokenIsFast(builder_, text, ErrorState.get(builder_).caseSensitive); + public static boolean consumeTokenFast(PsiBuilder builder, String text) { + int count = nextTokenIsFast(builder, text, ErrorState.get(builder).caseSensitive); if (count > 0) { - while (count-- > 0) builder_.advanceLexer(); + while (count-- > 0) builder.advanceLexer(); return true; } return false; } - public static boolean nextTokenIsFast(PsiBuilder builder_, IElementType token) { - return builder_.getTokenType() == token; + public static boolean nextTokenIsFast(PsiBuilder builder, IElementType token) { + return builder.getTokenType() == token; } - public static boolean nextTokenIsFast(PsiBuilder builder_, IElementType... tokens) { - IElementType tokenType = builder_.getTokenType(); + public static boolean nextTokenIsFast(PsiBuilder builder, IElementType... tokens) { + IElementType tokenType = builder.getTokenType(); for (IElementType token : tokens) { if (token == tokenType) return true; } return false; } - public static boolean nextTokenIs(PsiBuilder builder_, String frameName, IElementType... tokens) { - ErrorState state = ErrorState.get(builder_); + public static boolean nextTokenIs(PsiBuilder builder, String frameName, IElementType... tokens) { + ErrorState state = ErrorState.get(builder); if (state.completionState != null) return true; boolean track = !state.suppressErrors && state.predicateCount < 2 && state.predicateSign; - if (!track) return nextTokenIsFast(builder_, tokens); - IElementType tokenType = builder_.getTokenType(); + if (!track) return nextTokenIsFast(builder, tokens); + IElementType tokenType = builder.getTokenType(); if (StringUtil.isNotEmpty(frameName)) { - addVariantInner(state, builder_.rawTokenIndex(), frameName); + addVariantInner(state, builder.rawTokenIndex(), frameName); } else { for (IElementType token : tokens) { - addVariant(builder_, state, token); + addVariant(builder, state, token); } } if (tokenType == null) return false; @@ -242,23 +263,23 @@ public class GeneratedParserUtilBase { return false; } - public static boolean nextTokenIs(PsiBuilder builder_, IElementType token) { - if (!addVariantSmart(builder_, token, false)) return true; - return nextTokenIsFast(builder_, token); + public static boolean nextTokenIs(PsiBuilder builder, IElementType token) { + if (!addVariantSmart(builder, token, false)) return true; + return nextTokenIsFast(builder, token); } - public static boolean nextTokenIs(PsiBuilder builder_, String tokenText) { - if (!addVariantSmart(builder_, tokenText, false)) return true; - return nextTokenIsFast(builder_, tokenText, ErrorState.get(builder_).caseSensitive) > 0; + public static boolean nextTokenIs(PsiBuilder builder, String tokenText) { + if (!addVariantSmart(builder, tokenText, false)) return true; + return nextTokenIsFast(builder, tokenText, ErrorState.get(builder).caseSensitive) > 0; } - public static boolean nextTokenIsFast(PsiBuilder builder_, String tokenText) { - return nextTokenIsFast(builder_, tokenText, ErrorState.get(builder_).caseSensitive) > 0; + public static boolean nextTokenIsFast(PsiBuilder builder, String tokenText) { + return nextTokenIsFast(builder, tokenText, ErrorState.get(builder).caseSensitive) > 0; } - public static int nextTokenIsFast(PsiBuilder builder_, String tokenText, boolean caseSensitive) { - CharSequence sequence = builder_.getOriginalText(); - int offset = builder_.getCurrentOffset(); + public static int nextTokenIsFast(PsiBuilder builder, String tokenText, boolean caseSensitive) { + CharSequence sequence = builder.getOriginalText(); + int offset = builder.getCurrentOffset(); int endOffset = offset + tokenText.length(); CharSequence subSequence = sequence.subSequence(offset, Math.min(endOffset, sequence.length())); @@ -266,7 +287,7 @@ public class GeneratedParserUtilBase { int count = 0; while (true) { - int nextOffset = builder_.rawTokenTypeStart(++count); + int nextOffset = builder.rawTokenTypeStart(++count); if (nextOffset > endOffset) { return -count; } @@ -277,36 +298,36 @@ public class GeneratedParserUtilBase { return count; } - private static void addCompletionVariantSmart(PsiBuilder builder_, Object token) { - ErrorState state = ErrorState.get(builder_); + private static void addCompletionVariantSmart(PsiBuilder builder, Object token) { + ErrorState state = ErrorState.get(builder); CompletionState completionState = state.completionState; if (completionState != null && state.predicateCount == 0) { - addCompletionVariant(builder_, completionState, token); + addCompletionVariant(builder, completionState, token); } } - private static boolean addVariantSmart(PsiBuilder builder_, Object token, boolean force) { - ErrorState state = ErrorState.get(builder_); + private static boolean addVariantSmart(PsiBuilder builder, Object token, boolean force) { + ErrorState state = ErrorState.get(builder); // skip FIRST check in completion mode if (state.completionState != null && !force) return false; - builder_.eof(); + builder.eof(); if (!state.suppressErrors && state.predicateCount < 2) { - addVariant(builder_, state, token); + addVariant(builder, state, token); } return true; } - public static void addVariant(PsiBuilder builder_, String text) { - addVariant(builder_, ErrorState.get(builder_), text); + public static void addVariant(PsiBuilder builder, String text) { + addVariant(builder, ErrorState.get(builder), text); } - private static void addVariant(PsiBuilder builder_, ErrorState state, Object o) { - builder_.eof(); // skip whitespaces - addVariantInner(state, builder_.rawTokenIndex(), o); + private static void addVariant(PsiBuilder builder, ErrorState state, Object o) { + builder.eof(); // skip whitespaces + addVariantInner(state, builder.rawTokenIndex(), o); CompletionState completionState = state.completionState; if (completionState != null && state.predicateSign) { - addCompletionVariant(builder_, completionState, o); + addCompletionVariant(builder, completionState, o); } } @@ -323,9 +344,9 @@ public class GeneratedParserUtilBase { } } - private static void addCompletionVariant(@NotNull PsiBuilder builder_, @NotNull CompletionState completionState, Object o) { - int offset = builder_.getCurrentOffset(); - if (!builder_.eof() && offset == builder_.rawTokenTypeStart(1)) return; // suppress for zero-length tokens + private static void addCompletionVariant(@NotNull PsiBuilder builder, @NotNull CompletionState completionState, Object o) { + int offset = builder.getCurrentOffset(); + if (!builder.eof() && offset == builder.rawTokenTypeStart(1)) return; // suppress for zero-length tokens boolean add = false; int diff = completionState.offset - offset; @@ -336,18 +357,18 @@ public class GeneratedParserUtilBase { add = true; } else if (diff > 0 && diff <= length) { - CharSequence fragment = builder_.getOriginalText().subSequence(offset, completionState.offset); + CharSequence fragment = builder.getOriginalText().subSequence(offset, completionState.offset); add = completionState.prefixMatches(fragment.toString(), text); } else if (diff < 0) { for (int i=-1; ; i--) { - IElementType type = builder_.rawLookup(i); - int tokenStart = builder_.rawTokenTypeStart(i); - if (isWhitespaceOrComment(builder_, type)) { + IElementType type = builder.rawLookup(i); + int tokenStart = builder.rawTokenTypeStart(i); + if (isWhitespaceOrComment(builder, type)) { diff = completionState.offset - tokenStart; } else if (type != null && tokenStart < completionState.offset) { - CharSequence fragment = builder_.getOriginalText().subSequence(tokenStart, completionState.offset); + CharSequence fragment = builder.getOriginalText().subSequence(tokenStart, completionState.offset); if (completionState.prefixMatches(fragment.toString(), text)) { diff = completionState.offset - tokenStart; } @@ -360,12 +381,12 @@ public class GeneratedParserUtilBase { add = add && length > 1 && !(text.charAt(0) == '<' && text.charAt(length - 1) == '>') && !(text.charAt(0) == '\'' && text.charAt(length - 1) == '\'' && length < 5); if (add) { - completionState.addItem(builder_, text); + completionState.addItem(builder, text); } } - public static boolean isWhitespaceOrComment(@NotNull PsiBuilder builder_, @Nullable IElementType type) { - return ((PsiBuilderImpl)((Builder)builder_).getDelegate()).whitespaceOrComment(type); + public static boolean isWhitespaceOrComment(@NotNull PsiBuilder builder, @Nullable IElementType type) { + return ((PsiBuilderImpl)((Builder)builder).getDelegate()).whitespaceOrComment(type); } // here's the new section API for compact parsers & less IntelliJ platform API exposure @@ -377,35 +398,35 @@ public class GeneratedParserUtilBase { public static final int _NOT_ = 0x10; // simple enter/exit methods pair that doesn't require frame object - public static PsiBuilder.Marker enter_section_(PsiBuilder builder_) { - return builder_.mark(); + public static PsiBuilder.Marker enter_section_(PsiBuilder builder) { + return builder.mark(); } - public static void exit_section_(PsiBuilder builder_, + public static void exit_section_(PsiBuilder builder, PsiBuilder.Marker marker, @Nullable IElementType elementType, boolean result) { - close_marker_impl_(ErrorState.get(builder_).frameStack.peekLast(), marker, elementType, result); + close_marker_impl_(ErrorState.get(builder).frameStack.peekLast(), marker, elementType, result); } // complex enter/exit methods pair with frame object - public static PsiBuilder.Marker enter_section_(PsiBuilder builder_, int level, int modifiers, @Nullable String frameName) { - PsiBuilder.Marker marker = builder_.mark(); - enter_section_impl_(builder_, level, modifiers, frameName); + public static PsiBuilder.Marker enter_section_(PsiBuilder builder, int level, int modifiers, @Nullable String frameName) { + PsiBuilder.Marker marker = builder.mark(); + enter_section_impl_(builder, level, modifiers, frameName); return marker; } - private static void enter_section_impl_(PsiBuilder builder_, int level, int modifiers, @Nullable String frameName) { - ErrorState state = ErrorState.get(builder_); - Frame frame = state.FRAMES.alloc().init(builder_, state, level, modifiers, frameName); + private static void enter_section_impl_(PsiBuilder builder, int level, int modifiers, @Nullable String frameName) { + ErrorState state = ErrorState.get(builder); + Frame frame = state.FRAMES.alloc().init(builder, state, level, modifiers, frameName); Frame prevFrame = state.frameStack.peekLast(); if (prevFrame != null && prevFrame.errorReportedAt > frame.position) { // report error for previous unsuccessful frame - reportError(builder_, state, frame, true, false); + reportError(builder, state, frame, null, true, false); } if (((frame.modifiers & _LEFT_) | (frame.modifiers & _LEFT_INNER_)) != 0) { - PsiBuilder.Marker left = (PsiBuilder.Marker)builder_.getLatestDoneMarker(); - if (invalid_left_marker_guard_(builder_, left, frameName)) { + PsiBuilder.Marker left = (PsiBuilder.Marker)builder.getLatestDoneMarker(); + if (invalid_left_marker_guard_(builder, left, frameName)) { frame.leftMarker = left; } } @@ -427,14 +448,14 @@ public class GeneratedParserUtilBase { } } - public static void exit_section_(PsiBuilder builder_, + public static void exit_section_(PsiBuilder builder, int level, PsiBuilder.Marker marker, @Nullable IElementType elementType, boolean result, boolean pinned, @Nullable Parser eatMore) { - ErrorState state = ErrorState.get(builder_); + ErrorState state = ErrorState.get(builder); Frame frame = state.frameStack.pollLast(); if (frame == null || level != frame.level) { @@ -451,9 +472,19 @@ public class GeneratedParserUtilBase { state.FRAMES.recycle(frame); return; } - exit_section_impl_(state, frame, builder_, marker, elementType, result, pinned); + close_frame_impl_(state, frame, builder, marker, elementType, result, pinned); + exit_section_impl_(state, frame, builder, elementType, result, pinned, eatMore); + state.FRAMES.recycle(frame); + } - int initialPos = builder_.rawTokenIndex(); + private static void exit_section_impl_(ErrorState state, + Frame frame, + PsiBuilder builder, + @Nullable IElementType elementType, + boolean result, + boolean pinned, + @Nullable Parser eatMore) { + int initialPos = builder.rawTokenIndex(); boolean willFail = !result && !pinned; if (willFail && initialPos == frame.position && state.lastExpectedVariantPos == frame.position && frame.name != null && state.variants.size() - frame.variantCount > 1) { @@ -463,16 +494,16 @@ public class GeneratedParserUtilBase { int lastErrorPos = getLastVariantPos(state, initialPos); if (!state.suppressErrors && eatMore != null) { state.suppressErrors = true; - final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1); + final boolean eatMoreFlagOnce = !builder.eof() && eatMore.parse(builder, frame.level + 1); boolean eatMoreFlag = eatMoreFlagOnce || !result && frame.position == initialPos && lastErrorPos > frame.position; PsiBuilderImpl.ProductionMarker latestDoneMarker = (pinned || result) && (state.altMode || elementType != null) && - eatMoreFlagOnce ? (PsiBuilderImpl.ProductionMarker)builder_.getLatestDoneMarker() : null; + eatMoreFlagOnce ? (PsiBuilderImpl.ProductionMarker)builder.getLatestDoneMarker() : null; PsiBuilder.Marker extensionMarker = null; IElementType extensionTokenType = null; // whitespace prefix makes the very first frame offset bigger than marker start offset which is always 0 - if (latestDoneMarker instanceof PsiBuilder.Marker && + if (latestDoneMarker != null && frame.position >= latestDoneMarker.getStartIndex() && frame.position <= latestDoneMarker.getEndIndex()) { extensionMarker = ((PsiBuilder.Marker)latestDoneMarker).precede(); @@ -482,27 +513,27 @@ public class GeneratedParserUtilBase { // advance to the last error pos // skip tokens until lastErrorPos. parseAsTree might look better here... int parenCount = 0; - while ((eatMoreFlag || parenCount > 0) && builder_.rawTokenIndex() < lastErrorPos) { + while ((eatMoreFlag || parenCount > 0) && builder.rawTokenIndex() < lastErrorPos) { if (state.braces != null) { - if (builder_.getTokenType() == state.braces[0].getLeftBraceType()) parenCount ++; - else if (builder_.getTokenType() == state.braces[0].getRightBraceType()) parenCount --; + if (builder.getTokenType() == state.braces[0].getLeftBraceType()) parenCount ++; + else if (builder.getTokenType() == state.braces[0].getRightBraceType()) parenCount --; } - builder_.advanceLexer(); - eatMoreFlag = eatMore.parse(builder_, frame.level + 1); + builder.advanceLexer(); + eatMoreFlag = eatMore.parse(builder, frame.level + 1); } boolean errorReported = frame.errorReportedAt == initialPos || !result && frame.errorReportedAt >= frame.position; if (errorReported) { if (eatMoreFlag) { - builder_.advanceLexer(); - parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); + builder.advanceLexer(); + parseAsTree(state, builder, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); } } else if (eatMoreFlag) { - errorReported = reportError(builder_, state, frame, true, true); - parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); + errorReported = reportError(builder, state, frame, null, true, true); + parseAsTree(state, builder, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); } - else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex()) || frame.errorReportedAt > initialPos) { - errorReported = reportError(builder_, state, frame, true, false); + else if (eatMoreFlagOnce || (!result && frame.position != builder.rawTokenIndex()) || frame.errorReportedAt > initialPos) { + errorReported = reportError(builder, state, frame, null, true, false); } if (extensionMarker != null) { extensionMarker.done(extensionTokenType); @@ -518,7 +549,7 @@ public class GeneratedParserUtilBase { // do not report if there are errors beyond current position if (lastErrorPos == initialPos) { // do not force, inner recoverRoot might have skipped some tokens - reportError(builder_, state, frame, false, false); + reportError(builder, state, frame, elementType, false, false); } else if (lastErrorPos > initialPos) { // set error pos here as if it is reported for future reference @@ -530,19 +561,18 @@ public class GeneratedParserUtilBase { if (prevFrame != null && prevFrame.errorReportedAt < frame.errorReportedAt) { prevFrame.errorReportedAt = frame.errorReportedAt; } - state.FRAMES.recycle(frame); } - private static void exit_section_impl_(ErrorState state, - Frame frame, - PsiBuilder builder_, - PsiBuilder.Marker marker, - IElementType elementType, - boolean result, - boolean pinned) { + private static void close_frame_impl_(ErrorState state, + Frame frame, + PsiBuilder builder, + PsiBuilder.Marker marker, + IElementType elementType, + boolean result, + boolean pinned) { if (elementType != null && marker != null) { if ((frame.modifiers & _COLLAPSE_) != 0) { - PsiBuilderImpl.ProductionMarker last = result || pinned? (PsiBuilderImpl.ProductionMarker)builder_.getLatestDoneMarker() : null; + PsiBuilderImpl.ProductionMarker last = result || pinned? (PsiBuilderImpl.ProductionMarker)builder.getLatestDoneMarker() : null; if (last != null && last.getStartIndex() == frame.position && state.typeExtends(last.getTokenType(), elementType)) { IElementType resultType = last.getTokenType(); @@ -562,7 +592,7 @@ public class GeneratedParserUtilBase { frame.leftMarker.precede().done(elementType); } else { - if (frame.level == 0) builder_.eof(); // skip whitespaces + if (frame.level == 0) builder.eof(); // skip whitespaces marker.done(elementType); } } @@ -603,20 +633,20 @@ public class GeneratedParserUtilBase { } } - public static boolean report_error_(PsiBuilder builder_, boolean result_) { - if (!result_) report_error_(builder_, ErrorState.get(builder_), false); - return result_; + public static boolean report_error_(PsiBuilder builder, boolean result) { + if (!result) report_error_(builder, ErrorState.get(builder), false); + return result; } - public static void report_error_(PsiBuilder builder_, ErrorState state, boolean advance) { + public static void report_error_(PsiBuilder builder, ErrorState state, boolean advance) { Frame frame = state.frameStack.isEmpty()? null : state.frameStack.getLast(); if (frame == null) { LOG.error("unbalanced enter/exit section call: got null"); return; } - int position = builder_.rawTokenIndex(); + int position = builder.rawTokenIndex(); if (frame.errorReportedAt < position && getLastVariantPos(state, position + 1) <= position) { - reportError(builder_, state, frame, true, advance); + reportError(builder, state, frame, null, true, advance); } } @@ -624,28 +654,43 @@ public class GeneratedParserUtilBase { return state.lastExpectedVariantPos < 0? defValue : state.lastExpectedVariantPos; } - private static boolean reportError(PsiBuilder builder_, + private static boolean reportError(PsiBuilder builder, ErrorState state, Frame frame, + IElementType elementType, boolean force, boolean advance) { - String expectedText = state.getExpectedText(builder_); + String expectedText = state.getExpectedText(builder); boolean notEmpty = StringUtil.isNotEmpty(expectedText); if (force || notEmpty || advance) { - String gotText = builder_.eof()? "unexpected end of file" : - notEmpty? "got '" + builder_.getTokenText() +"'" : - "'" + builder_.getTokenText() +"' unexpected"; + String gotText = builder.eof()? "unexpected end of file" : + notEmpty? "got '" + builder.getTokenText() +"'" : + "'" + builder.getTokenText() +"' unexpected"; String message = expectedText + gotText; if (advance) { - PsiBuilder.Marker mark = builder_.mark(); - builder_.advanceLexer(); + PsiBuilder.Marker mark = builder.mark(); + builder.advanceLexer(); mark.error(message); } - else { - builder_.error(message); + else if (!force) { + PsiBuilder.Marker extensionMarker = null; + IElementType extensionTokenType = null; + PsiBuilderImpl.ProductionMarker latestDoneMarker = elementType == null ? null : (PsiBuilderImpl.ProductionMarker)builder.getLatestDoneMarker(); + if (latestDoneMarker != null && + frame.position >= latestDoneMarker.getStartIndex() && + frame.position <= latestDoneMarker.getEndIndex()) { + extensionMarker = ((PsiBuilder.Marker)latestDoneMarker).precede(); + extensionTokenType = latestDoneMarker.getTokenType(); + ((PsiBuilder.Marker)latestDoneMarker).drop(); + } + builder.error(message); + if (extensionMarker != null) extensionMarker.done(extensionTokenType); } - builder_.eof(); // skip whitespaces - frame.errorReportedAt = builder_.rawTokenIndex(); + else { + builder.error(message); + } + builder.eof(); // skip whitespaces + frame.errorReportedAt = builder.rawTokenIndex(); return true; } return false; @@ -689,8 +734,8 @@ public class GeneratedParserUtilBase { public final ErrorState state; public final PsiParser parser; - public Builder(PsiBuilder builder_, ErrorState state_, PsiParser parser_) { - super(builder_); + public Builder(PsiBuilder builder, ErrorState state_, PsiParser parser_) { + super(builder); state = state_; parser = parser_; } @@ -764,13 +809,12 @@ public class GeneratedParserUtilBase { if (state.braces != null && state.braces.length == 0) state.braces = null; } - public String getExpectedText(PsiBuilder builder_) { - int position = builder_.rawTokenIndex(); + public String getExpectedText(PsiBuilder builder) { + int position = builder.rawTokenIndex(); StringBuilder sb = new StringBuilder(); if (addExpected(sb, position, true)) { sb.append(" expected, "); } - else if (addExpected(sb, position, false)) sb.append(" unexpected, "); return sb.toString(); } @@ -825,14 +869,14 @@ public class GeneratedParserUtilBase { list.setSize(start); } - boolean typeExtends(IElementType child_, IElementType parent_) { - if (child_ == parent_) return true; + boolean typeExtends(IElementType child, IElementType parent) { + if (child == parent) return true; if (extendsSets != null) { for (TokenSet set : extendsSets) { - if (set.contains(child_) && set.contains(parent_)) return true; + if (set.contains(child) && set.contains(parent)) return true; } } - return altExtendsChecker != null && altExtendsChecker.process(child_, parent_); + return altExtendsChecker != null && altExtendsChecker.process(child, parent); } } @@ -850,9 +894,9 @@ public class GeneratedParserUtilBase { public Frame() { } - public Frame init(PsiBuilder builder_, ErrorState state, int level_, int modifiers_, String name_) { - offset = builder_.getCurrentOffset(); - position = builder_.rawTokenIndex(); + public Frame init(PsiBuilder builder, ErrorState state, int level_, int modifiers_, String name_) { + offset = builder.getCurrentOffset(); + position = builder.rawTokenIndex(); level = level_; modifiers = modifiers_; name = name_; @@ -916,7 +960,7 @@ public class GeneratedParserUtilBase { private static final int MAX_CHILDREN_IN_TREE = 10; - public static boolean parseAsTree(ErrorState state, final PsiBuilder builder_, int level, final IElementType chunkType, + public static boolean parseAsTree(ErrorState state, final PsiBuilder builder, int level, final IElementType chunkType, boolean checkBraces, final Parser parser, final Parser eatMoreCondition) { final LinkedList> parenList = new LinkedList>(); final LinkedList> siblingList = new LinkedList>(); @@ -952,14 +996,14 @@ public class GeneratedParserUtilBase { int tokenCount = 0; if (checkParens) { int tokenIdx = -1; - while (builder_.rawLookup(tokenIdx) == TokenType.WHITE_SPACE) tokenIdx --; - LighterASTNode doneMarker = builder_.rawLookup(tokenIdx) == state.braces[0].getLeftBraceType() ? builder_.getLatestDoneMarker() : null; - if (doneMarker != null && doneMarker.getStartOffset() == builder_.rawTokenTypeStart(tokenIdx) && doneMarker.getTokenType() == TokenType.ERROR_ELEMENT) { + while (builder.rawLookup(tokenIdx) == TokenType.WHITE_SPACE) tokenIdx --; + LighterASTNode doneMarker = builder.rawLookup(tokenIdx) == state.braces[0].getLeftBraceType() ? builder.getLatestDoneMarker() : null; + if (doneMarker != null && doneMarker.getStartOffset() == builder.rawTokenTypeStart(tokenIdx) && doneMarker.getTokenType() == TokenType.ERROR_ELEMENT) { parenList.add(Pair.create(((PsiBuilder.Marker)doneMarker).precede(), (PsiBuilder.Marker)null)); } } while (true) { - final IElementType tokenType = builder_.getTokenType(); + final IElementType tokenType = builder.getTokenType(); if (checkParens && (tokenType == state.braces[0].getLeftBraceType() || tokenType == state.braces[0].getRightBraceType() && !parenList.isEmpty())) { if (marker != null) { marker.done(chunkType); @@ -969,10 +1013,10 @@ public class GeneratedParserUtilBase { } if (tokenType == state.braces[0].getLeftBraceType()) { final Pair prev = siblingList.peek(); - parenList.addFirst(Pair.create(builder_.mark(), prev == null ? null : prev.first)); + parenList.addFirst(Pair.create(builder.mark(), prev == null ? null : prev.first)); } checkSiblingsRunnable.run(); - builder_.advanceLexer(); + builder.advanceLexer(); if (tokenType == state.braces[0].getRightBraceType()) { final Pair pair = parenList.removeFirst(); pair.first.done(chunkType); @@ -986,10 +1030,10 @@ public class GeneratedParserUtilBase { } else { if (marker == null) { - marker = builder_.mark(); + marker = builder.mark(); marker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_LEFT_BINDER, null); } - final boolean result = (!parenList.isEmpty() || eatMoreCondition.parse(builder_, level + 1)) && parser.parse(builder_, level + 1); + final boolean result = (!parenList.isEmpty() || eatMoreCondition.parse(builder, level + 1)) && parser.parse(builder, level + 1); if (result) { tokenCount++; totalCount++; @@ -1016,7 +1060,7 @@ public class GeneratedParserUtilBase { return totalCount != 0; } - private static class DummyBlockElementType extends IElementType implements ICompositeElementType{ + private static class DummyBlockElementType extends IElementType implements ICompositeElementType { DummyBlockElementType() { super("DUMMY_BLOCK", Language.ANY); } diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java index 3e0207c5e9e0..38558196e6ff 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java @@ -16,10 +16,10 @@ package com.intellij.openapi.components.impl.stores; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.StateStorageOperation; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.module.Module; -import com.intellij.openapi.application.PathManager; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,7 +34,7 @@ class ModuleStateStorageManager extends StateStorageManagerImpl { } @Override - protected StorageData createStorageData(String storageSpec) { + protected StorageData createStorageData(@NotNull String storageSpec) { return new ModuleStoreImpl.ModuleFileData(ROOT_TAG_NAME, myModule); } diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java index f550fa1db3d0..ec07d50986bd 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java @@ -159,12 +159,12 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM @Nullable @Override - public Set getChangedComponentNames(@NotNull StorageData storageData, @Nullable PathMacroSubstitutor substitutor) { - final ModuleFileData data = (ModuleFileData)storageData; + public Set getChangedComponentNames(@NotNull StorageData newStorageData, @Nullable PathMacroSubstitutor substitutor) { + final ModuleFileData data = (ModuleFileData)newStorageData; if (!myOptions.equals(data.myOptions)) { return null; } - return super.getChangedComponentNames(storageData, substitutor); + return super.getChangedComponentNames(newStorageData, substitutor); } public void setOption(final String optionName, final String optionValue) { diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java index 80872cecd9f1..fb4e2e67732c 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java @@ -17,8 +17,9 @@ package com.intellij.profile.codeInspection.ui; import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.PopupStep; @@ -38,7 +39,7 @@ import java.awt.*; /** * @author Dmitry Batkovich */ -public abstract class AdvancedSettingsAction extends AnAction { +public abstract class AdvancedSettingsAction extends DumbAwareAction { private final int myCheckBoxIndent; private Project myProject; private InspectionConfigTreeNode myRoot; diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java index df3b8bda3f3b..f8fdecd3020b 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java @@ -22,11 +22,12 @@ import com.intellij.codeInsight.daemon.impl.SeverityUtil; import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.SeverityEditorDialog; import com.intellij.lang.annotation.HighlightSeverity; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.profile.codeInspection.SeverityProvider; import org.jetbrains.annotations.NotNull; @@ -37,7 +38,7 @@ import java.util.TreeSet; /** * @author Dmitry Batkovich */ -public abstract class LevelChooserAction extends ComboBoxAction { +public abstract class LevelChooserAction extends ComboBoxAction implements DumbAware { private final SeverityRegistrar mySeverityRegistrar; private HighlightSeverity myChosen = null; @@ -62,7 +63,7 @@ public abstract class LevelChooserAction extends ComboBoxAction { group.add(action); } group.addSeparator(); - group.add(new AnAction("Edit severities...") { + group.add(new DumbAwareAction("Edit severities...") { @Override public void actionPerformed(final AnActionEvent e) { final SeverityEditorDialog dlg = new SeverityEditorDialog(anchor, myChosen, mySeverityRegistrar); @@ -101,7 +102,7 @@ public abstract class LevelChooserAction extends ComboBoxAction { templatePresentation.setIcon(HighlightDisplayLevel.find(severity).getIcon()); } - private class HighlightSeverityAction extends AnAction { + private class HighlightSeverityAction extends DumbAwareAction { private final HighlightSeverity mySeverity; public HighlightSeverity getSeverity() { diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java index fde3b141084d..d5a6ac7b0e3f 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java @@ -17,10 +17,11 @@ package com.intellij.profile.codeInspection.ui; import com.intellij.codeInspection.ex.Descriptor; import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.psi.search.scope.NonProjectFilesScope; import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx; @@ -31,14 +32,14 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.ArrayList; -import java.util.Set; -import java.util.List; import java.util.Collections; +import java.util.List; +import java.util.Set; /** * @author Dmitry Batkovich */ -public abstract class ScopesChooser extends ComboBoxAction { +public abstract class ScopesChooser extends ComboBoxAction implements DumbAware { public static final String TITLE = "Select a scope to change its settings"; private final List myDefaultDescriptors; @@ -82,7 +83,7 @@ public abstract class ScopesChooser extends ComboBoxAction { fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames); group.addSeparator(); - group.add(new AnAction("Edit Scopes Order...") { + group.add(new DumbAwareAction("Edit Scopes Order...") { @Override public void actionPerformed(final AnActionEvent e) { final ScopesOrderDialog dlg = new ScopesOrderDialog(component, myInspectionProfile, myProject); @@ -110,7 +111,7 @@ public abstract class ScopesChooser extends ComboBoxAction { if (excludedScopeNames.contains(scopeName)) { continue; } - group.add(new AnAction(scopeName) { + group.add(new DumbAwareAction(scopeName) { @Override public void actionPerformed(final AnActionEvent e) { for (final Descriptor defaultDescriptor : defaultDescriptors) { diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index e086d9aa9610..fbcbe1a6d0d1 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -38,6 +38,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.Splitter; @@ -64,7 +65,8 @@ import com.intellij.ui.components.JBLabel; import com.intellij.util.Alarm; import com.intellij.util.Function; import com.intellij.util.config.StorageAccessors; -import com.intellij.util.containers.*; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Convertor; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xml.util.XmlStringUtil; @@ -86,7 +88,6 @@ import java.awt.*; import java.io.IOException; import java.io.StringReader; import java.util.*; -import java.util.HashSet; import java.util.List; /** @@ -365,7 +366,7 @@ public class SingleInspectionProfilePanel extends JPanel { actions.add(actionManager.createExpandAllAction(myTreeExpander, myTreeTable)); actions.add(actionManager.createCollapseAllAction(myTreeExpander, myTreeTable)); - actions.add(new AnAction("Reset to Empty", "Reset to empty", AllIcons.Actions.Reset_to_empty){ + actions.add(new DumbAwareAction("Reset to Empty", "Reset to empty", AllIcons.Actions.Reset_to_empty){ @Override public void update(AnActionEvent e) { diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java index 75146cbb36a5..155d95ce7213 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java @@ -22,6 +22,8 @@ import com.intellij.icons.AllIcons; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.CheckboxAction; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.profile.codeInspection.SeverityProvider; import com.intellij.profile.codeInspection.ui.LevelChooserAction; import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; @@ -32,7 +34,7 @@ import java.util.SortedSet; /** * @author Dmitry Batkovich */ -public class InspectionFilterAction extends DefaultActionGroup implements Toggleable { +public class InspectionFilterAction extends DefaultActionGroup implements Toggleable, DumbAware { private final SeverityRegistrar mySeverityRegistrar; private final InspectionsFilter myInspectionsFilter; @@ -69,7 +71,7 @@ public class InspectionFilterAction extends DefaultActionGroup implements Toggle add(new ShowOnlyCleanupInspectionsAction()); } - private class ResetFilterAction extends AnAction { + private class ResetFilterAction extends DumbAwareAction { public ResetFilterAction() { super("Reset Filter"); } @@ -86,7 +88,7 @@ public class InspectionFilterAction extends DefaultActionGroup implements Toggle } } - private class ShowOnlyCleanupInspectionsAction extends CheckboxAction { + private class ShowOnlyCleanupInspectionsAction extends CheckboxAction implements DumbAware{ public ShowOnlyCleanupInspectionsAction() { super("Show Only Cleanup Inspections"); } @@ -102,7 +104,7 @@ public class InspectionFilterAction extends DefaultActionGroup implements Toggle } } - private class ShowAvailableOnlyOnAnalyzeInspectionsAction extends CheckboxAction { + private class ShowAvailableOnlyOnAnalyzeInspectionsAction extends CheckboxAction implements DumbAware { public ShowAvailableOnlyOnAnalyzeInspectionsAction() { super("Show Only \"Available only for Analyze | Inspect Code\""); @@ -119,7 +121,7 @@ public class InspectionFilterAction extends DefaultActionGroup implements Toggle } } - private class ShowWithSpecifiedSeverityInspectionsAction extends CheckboxAction { + private class ShowWithSpecifiedSeverityInspectionsAction extends CheckboxAction implements DumbAware { private final HighlightSeverity mySeverity; @@ -146,7 +148,7 @@ public class InspectionFilterAction extends DefaultActionGroup implements Toggle } } - private class ShowEnabledOrDisabledInspectionsAction extends CheckboxAction { + private class ShowEnabledOrDisabledInspectionsAction extends CheckboxAction implements DumbAware{ private final Boolean myShowEnabledActions; diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java index 94ba8865d504..45f83ebbaf95 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java @@ -341,13 +341,6 @@ public class InspectionsConfigTreeTable extends TreeTable { if (myScopeToAverageSeverityMap.size() == 1) { return result; } - String[] scopesOrder = inspectionProfile.getScopesOrder(); - if (scopesOrder == null || scopesOrder.length == 0) { - final ArrayList scopesList = new ArrayList(myScopeToAverageSeverityMap.keySet()); - scopesList.remove(myDefaultScopeName); - ContainerUtil.sort(scopesList); - scopesOrder = ArrayUtil.toStringArray(scopesList); - } final SeverityAndOccurrences defaultSeveritiesAndOccurrences = myScopeToAverageSeverityMap.get(myDefaultScopeName); if (defaultSeveritiesAndOccurrences == null) { @@ -361,15 +354,15 @@ public class InspectionsConfigTreeTable extends TreeTable { } final int allInspectionsCount = defaultSeveritiesAndOccurrences.getOccurrencesSize(); final Map allScopes = defaultSeveritiesAndOccurrences.getOccurrences(); - String[] reversedScopesOrder = ArrayUtil.reverseArray(scopesOrder); - for (String currentScope : reversedScopesOrder) { + for (String currentScope : myScopeToAverageSeverityMap.keySet()) { final SeverityAndOccurrences currentSeverityAndOccurrences = myScopeToAverageSeverityMap.get(currentScope); if (currentSeverityAndOccurrences == null) { continue; } final HighlightSeverity currentSeverity = currentSeverityAndOccurrences.getPrimarySeverity(); if (currentSeverity == ScopesAndSeveritiesTable.MIXED_FAKE_SEVERITY || - currentSeverityAndOccurrences.getOccurrencesSize() == allInspectionsCount) { + currentSeverityAndOccurrences.getOccurrencesSize() == allInspectionsCount || + myDefaultScopeName.equals(currentScope)) { result.put(currentScope, currentSeverity); } else { diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index ffc7de7c9b12..99b5d861cf5e 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -130,7 +130,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe if (needRebuild) { LOG.info("Version has changed for stub index " + extension.getKey() + ". The index will be rebuilt."); } - FileUtil.delete(indexRootDir); + FileUtil.deleteWithRenaming(indexRootDir); IndexingStamp.rewriteVersion(versionFile, version); // todo snapshots indices } @@ -164,7 +164,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe private static void onExceptionInstantiatingIndex(int version, File versionFile, File indexRootDir, Exception e) throws IOException { LOG.info(e); - FileUtil.delete(indexRootDir); + FileUtil.deleteWithRenaming(indexRootDir); IndexingStamp.rewriteVersion(versionFile, version); // todo snapshots indices } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 019b3172817f..d90c2debd02d 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -380,9 +380,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { LOG.info("Version has changed for index " + name + ". The index will be rebuilt."); } if (extension.hasSnapshotMapping() && (isCurrentVersionCorrupted || versionChanged)) { - FileUtil.delete(IndexInfrastructure.getPersistentIndexRootDir(name)); + FileUtil.deleteWithRenaming(IndexInfrastructure.getPersistentIndexRootDir(name)); } - FileUtil.delete(IndexInfrastructure.getIndexRootDir(name)); + FileUtil.deleteWithRenaming(IndexInfrastructure.getIndexRootDir(name)); IndexingStamp.rewriteVersion(versionFile, version); } @@ -458,10 +458,10 @@ public class FileBasedIndexImpl extends FileBasedIndex { catch (Exception ignored) { } - FileUtil.delete(IndexInfrastructure.getIndexRootDir(name)); + FileUtil.deleteWithRenaming(IndexInfrastructure.getIndexRootDir(name)); if (extension.hasSnapshotMapping() && (!contentHashesEnumeratorOk || instantiatedStorage)) { - FileUtil.delete(IndexInfrastructure.getPersistentIndexRootDir(name)); + FileUtil.deleteWithRenaming(IndexInfrastructure.getPersistentIndexRootDir(name)); // todo there is possibility of corruption of storage and content hashes } IndexingStamp.rewriteVersion(versionFile, version); } @@ -1564,7 +1564,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { indicesToDrop.remove(key.toString()); } for (String s : indicesToDrop) { - FileUtil.delete(IndexInfrastructure.getIndexRootDir(ID.create(s))); + FileUtil.deleteWithRenaming(IndexInfrastructure.getIndexRootDir(ID.create(s))); } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java index 5ef1379eaaf4..1e8f43edf062 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java @@ -68,7 +68,7 @@ public class IndexingStamp { public static synchronized void rewriteVersion(@NotNull final File file, final int version) throws IOException { final long prevLastModifiedValue = file.lastModified(); if (file.exists()) { - FileUtil.delete(file); + FileUtil.deleteWithRenaming(file); } file.getParentFile().mkdirs(); final DataOutputStream os = FileUtilRt.doIOOperation(new FileUtilRt.RepeatableIOOperation() { diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java index a9a87bac411b..98f6b1f1348c 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements VirtualFileManagerListener, CommandListener { private static final Key WAS_VERSIONED_KEY = @@ -89,19 +90,25 @@ public class LocalHistoryEventDispatcher extends VirtualFileAdapter implements V } private void createRecursively(VirtualFile f) { - if (isVersioned(f)) { - myVcs.created(f.getPath(), f.isDirectory()); - } - if (f.isDirectory()) { - // For unversioned files we try to get cached children in hope that they are already generated by content root manager: - // cached children may mean that there are versioned sub-folders or sub-files. - Iterable children = myGateway.isVersioned(f, true) - ? IdeaGateway.loadAndIterateChildren(f) - : IdeaGateway.iterateDBChildren(f); - for (VirtualFile each : children) { - createRecursively(each); + VfsUtilCore.visitChildrenRecursively(f, new VirtualFileVisitor() { + @Override + public boolean visitFile(@NotNull VirtualFile f) { + if (isVersioned(f)) { + myVcs.created(f.getPath(), f.isDirectory()); + } + return true; } - } + + @Nullable + @Override + public Iterable getChildrenIterable(@NotNull VirtualFile f) { + // For unversioned files we try to get cached children in hope that they are already generated by content root manager: + // cached children may mean that there are versioned sub-folders or sub-files. + return myGateway.isVersioned(f, true) + ? IdeaGateway.loadAndIterateChildren(f) + : IdeaGateway.iterateDBChildren(f); + } + }); } @Override diff --git a/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java index 182d347de4c1..2b8cdd2a9884 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java @@ -42,15 +42,7 @@ public class PtyCommandLine extends GeneralCommandLine { protected Process startProcess(@NotNull List commands) throws IOException { if (SystemInfo.isUnix) { try { - Map env = Maps.newHashMap(); - setupEnvironment(env); - - if (isRedirectErrorStream()) { - LOG.error("Launching process with PTY and redirected error stream is unsupported yet"); - } - - File workDirectory = getWorkDirectory(); - return PtyProcess.exec(ArrayUtil.toStringArray(commands), env, workDirectory != null ? workDirectory.getPath() : null, true); + return startProcessWithPty(commands, true); } catch (Throwable e) { LOG.error("Couldn't run process with PTY", e); @@ -59,4 +51,17 @@ public class PtyCommandLine extends GeneralCommandLine { return super.startProcess(commands); } + + @NotNull + public Process startProcessWithPty(@NotNull List commands, boolean console) throws IOException { + Map env = Maps.newHashMap(); + setupEnvironment(env); + + if (isRedirectErrorStream()) { + LOG.error("Launching process with PTY and redirected error stream is unsupported yet"); + } + + File workDirectory = getWorkDirectory(); + return PtyProcess.exec(ArrayUtil.toStringArray(commands), env, workDirectory != null ? workDirectory.getPath() : null, console); + } } diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index 17efbb4d61df..a5325ad0a98e 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -242,6 +242,9 @@ public interface IdeActions { @NonNls String GROUP_GUI_DESIGNER_COMPONENT_TREE_POPUP = "GuiDesigner.ComponentTreePopupMenu"; @NonNls String GROUP_GUI_DESIGNER_PROPERTY_INSPECTOR_POPUP = "GuiDesigner.PropertyInspectorPopupMenu"; + @NonNls String ACTION_GOTO_LAST_CHANGE = "JumpToLastChange"; + @NonNls String ACTION_GOTO_NEXT_CHANGE = "JumpToNextChange"; + @NonNls String ACTION_GOTO_BACK = "Back"; @NonNls String ACTION_GOTO_FORWARD = "Forward"; @NonNls String ACTION_GOTO_DECLARATION = "GotoDeclaration"; diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index d263288634b7..67d655fd0bad 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -19,6 +19,7 @@ import com.intellij.execution.filters.Filter; import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.execution.filters.HyperlinkInfoBase; import com.intellij.ide.OccurenceNavigator; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; @@ -59,6 +60,7 @@ import java.util.Map; * @author peter */ public class EditorHyperlinkSupport { + private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.EditorHyperlinkSupport"); public static final Key OLD_HYPERLINK_TEXT_ATTRIBUTES = Key.create("OLD_HYPERLINK_TEXT_ATTRIBUTES"); private static final Key HYPERLINK = Key.create("HYPERLINK"); private static final int HYPERLINK_LAYER = HighlighterLayer.SELECTION - 123; @@ -266,11 +268,19 @@ public class EditorHyperlinkSupport { Filter.Result result = customFilter.applyFilter(text, endOffset); if (result != null) { for (Filter.ResultItem resultItem : result.getResultItems()) { - if (resultItem.getHyperlinkInfo() != null) { - createHyperlink(resultItem.getHighlightStartOffset(), resultItem.getHighlightEndOffset(), resultItem.getHighlightAttributes(), resultItem.getHyperlinkInfo()); + int start = resultItem.getHighlightStartOffset(); + int end = resultItem.getHighlightEndOffset(); + if (end < start || end > document.getTextLength()) { + LOG.error("Filter returned wrong range: start=" + start + "; end=" + end + "; length=" + document.getTextLength() + "; filter=" + customFilter); + continue; } - else if (resultItem.getHighlightAttributes() != null) { - addHighlighter(resultItem.getHighlightStartOffset(), resultItem.getHighlightEndOffset(), resultItem.getHighlightAttributes()); + + TextAttributes attributes = resultItem.getHighlightAttributes(); + if (resultItem.getHyperlinkInfo() != null) { + createHyperlink(start, end, attributes, resultItem.getHyperlinkInfo()); + } + else if (attributes != null) { + addHighlighter(start, end, attributes); } } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/JumpToNextEditAction.java b/platform/platform-impl/src/com/intellij/ide/actions/JumpToNextEditAction.java new file mode 100644 index 000000000000..5890b4757cdb --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/JumpToNextEditAction.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.actions; + +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +public class JumpToNextEditAction extends AnAction implements DumbAware { + public void actionPerformed(@NotNull AnActionEvent e) { + Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); + if (project == null) return; + IdeDocumentHistory.getInstance(project).navigateNextChange(); + } + + public void update(@NotNull AnActionEvent e){ + Presentation presentation = e.getPresentation(); + DataContext dataContext = e.getDataContext(); + Project project = CommonDataKeys.PROJECT.getData(dataContext); + if (project == null) { + presentation.setEnabled(false); + return; + } + presentation.setEnabled(IdeDocumentHistory.getInstance(project).isNavigateNextChangeAvailable()); + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java index cd108befbe1a..0bab1797b8e0 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java @@ -318,9 +318,15 @@ public class InstalledPluginsManagerMain extends PluginManagerMain { public boolean isModified() { final boolean modified = super.isModified(); if (modified) return true; + final List disabledPlugins = PluginManagerCore.getDisabledPlugins(); for (int i = 0; i < pluginsModel.getRowCount(); i++) { final IdeaPluginDescriptor pluginDescriptor = pluginsModel.getObjectAt(i); - if (pluginDescriptor.isEnabled() != ((InstalledPluginsTableModel)pluginsModel).isEnabled(pluginDescriptor.getPluginId())) { + final PluginId pluginId = pluginDescriptor.getPluginId(); + final boolean enabledInTable = ((InstalledPluginsTableModel)pluginsModel).isEnabled(pluginId); + if (pluginDescriptor.isEnabled() != enabledInTable) { + if (enabledInTable && !disabledPlugins.contains(pluginId.getIdString())) { + continue; //was disabled automatically on startup + } return true; } } @@ -330,7 +336,6 @@ public class InstalledPluginsManagerMain extends PluginManagerMain { return true; } } - final List disabledPlugins = PluginManagerCore.getDisabledPlugins(); for (Map.Entry entry : ((InstalledPluginsTableModel)pluginsModel).getEnabledMap().entrySet()) { final Boolean enabled = entry.getValue(); if (enabled != null && !enabled.booleanValue() && !disabledPlugins.contains(entry.getKey().toString())) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java index fd8e303cd680..f2194713a595 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeVersion.java @@ -32,6 +32,7 @@ import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.projectImport.ProjectOpenProcessor; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -42,7 +43,7 @@ import java.util.Set; public interface MergeVersion { Document createWorkingDocument(Project project); - void applyText(String text, Project project); + void applyText(@NotNull String text, Project project); @Nullable VirtualFile getFile(); @@ -91,7 +92,7 @@ public interface MergeVersion { } @Override - public void applyText(final String text, final Project project) { + public void applyText(@NotNull final String text, final Project project) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { @@ -105,24 +106,21 @@ public interface MergeVersion { }); } - protected void doApplyText(String text, Project project) { + protected void doApplyText(@NotNull String text, Project project) { setDocumentText(myDocument, text, DiffBundle.message("save.merge.result.command.name"), project); FileDocumentManager.getInstance().saveDocument(myDocument); - final VirtualFile file = getFile(); - reportProjectFileChangeIfNeeded(project, file); + reportProjectFileChangeIfNeeded(project, getFile()); } - public static void reportProjectFileChangeIfNeeded(Project project, @Nullable VirtualFile file) { - if (file != null && !file.isDirectory()) { - if (ProjectCoreUtil.isProjectOrWorkspaceFile(file) || isProjectFile(file)) { - ProjectManagerEx.getInstanceEx().saveChangedProjectFile(file, project); - } + public static void reportProjectFileChangeIfNeeded(@Nullable Project project, @Nullable VirtualFile file) { + if (project != null && file != null && !file.isDirectory() && (ProjectCoreUtil.isProjectOrWorkspaceFile(file) || isProjectFile(file))) { + ProjectManagerEx.getInstanceEx().saveChangedProjectFile(file, project); } } @Nullable - public static Runnable prepareToReportChangedProjectFiles(final Project project, final Collection files) { + public static Runnable prepareToReportChangedProjectFiles(@NotNull final Project project, final Collection files) { final Set vfs = new HashSet(); for (VirtualFile vf : files) { if (vf != null && ! vf.isDirectory()) { @@ -157,7 +155,7 @@ public interface MergeVersion { return importProvider != null && importProvider.lookForProjectsInDirectory(); } - protected void doRestoreOriginalContent(Project project) { + protected void doRestoreOriginalContent(@Nullable Project project) { setDocumentText(myDocument, myTextBeforeMerge, "", project); } @@ -181,7 +179,7 @@ public interface MergeVersion { return file.getFileType(); } - private static void setDocumentText(final Document document, final String text, String name, Project project) { + private static void setDocumentText(@NotNull final Document document, @NotNull final String text, @Nullable String name, @Nullable Project project) { CommandProcessor.getInstance().executeCommand(project, new Runnable() { @Override public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineActionHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineActionHandler.java index f09a53c8ae99..b64040de3ef6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineActionHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineActionHandler.java @@ -56,11 +56,6 @@ class CutLineActionHandler extends EditorWriteActionHandler { int lineEndOffset = doc.getLineEndOffset(lineNumber); int lineStartOffset = doc.getLineStartOffset(lineNumber); - if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets() - && caretOffset == (myToLineStart ? lineStartOffset : lineEndOffset)) { - return; - } - int start; int end; if (myToLineStart) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java index 5785f01feb33..b97e0cdaa2d9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java @@ -18,6 +18,7 @@ package com.intellij.openapi.editor.actions; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; @@ -45,16 +46,10 @@ public class DeleteToWordEndAction extends TextComponentEditorAction { } @Override - public void executeWriteAction(Editor editor, DataContext dataContext) { + public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) { CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP); CopyPasteManager.getInstance().stopKillRings(); - int lineNumber = editor.getCaretModel().getLogicalPosition().line; - if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets() - && editor.getCaretModel().getOffset() == editor.getDocument().getLineEndOffset(lineNumber)) { - return; - } - boolean camelMode = editor.getSettings().isCamelWords(); if (myNegateCamelMode) { camelMode = !camelMode; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/IdeDocumentHistory.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/IdeDocumentHistory.java index 61e1a640612a..eeda21830d80 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/IdeDocumentHistory.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/IdeDocumentHistory.java @@ -1,6 +1,6 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,9 @@ public abstract class IdeDocumentHistory { public abstract boolean isForwardAvailable(); public abstract void navigatePreviousChange(); + public abstract void navigateNextChange(); public abstract boolean isNavigatePreviousChangeAvailable(); + public abstract boolean isNavigateNextChangeAvailable(); public abstract VirtualFile[] getChangedFiles(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java index b8f453453a50..88d83ffb63c1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java @@ -259,11 +259,10 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec } private void setCurrentChangePlace() { - final Pair selectedEditorWithProvider = getSelectedEditor(); - if (selectedEditorWithProvider == null) { + final PlaceInfo placeInfo = getCurrentPlaceInfo(); + if (placeInfo == null) { return; } - final PlaceInfo placeInfo = createPlaceInfo(selectedEditorWithProvider.getFirst(), selectedEditorWithProvider.getSecond ()); final VirtualFile file = placeInfo.getFile(); if (myChangedFilesInCurrentCommand.contains(file)) { @@ -318,13 +317,8 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec myStartIndex = 0; myCurrentIndex = 0; - if (myCurrentChangePlace != null) { - myCurrentChangePlace = null; - } - - if (myCommandStartPlace != null) { - myCommandStartPlace = null; - } + myCurrentChangePlace = null; + myCommandStartPlace = null; } @Override @@ -426,6 +420,27 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec } } + @Override + public void navigateNextChange() { + removeInvalidFilesFromStacks(); + if (myCurrentIndex >= myStartIndex + myChangePlaces.size() - 1) return; + int index = myCurrentIndex + 1; + final PlaceInfo info = myChangePlaces.get(index - myStartIndex); + + executeCommand(new Runnable() { + @Override + public void run() { + gotoPlaceInfo(info); + } + }, "", null); + myCurrentIndex = index; + } + + @Override + public boolean isNavigateNextChangeAvailable() { + return myCurrentIndex < myStartIndex + myChangePlaces.size() - 1; + } + private static boolean removeInvalidFilesFrom(@NotNull List backPlaces) { boolean removed = false; for (Iterator iterator = backPlaces.iterator(); iterator.hasNext();) { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java index 67fe6cb4ed86..381bb7159796 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java @@ -136,6 +136,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd myBuilder = new MyBuilder(new SimpleTreeStructure.Impl(myRoot)); myBuilder.setFilteringMerge(300, null); + setMinimumSize(new Dimension(200, 100)); Disposer.register(this, myBuilder); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java index 0273c7dbf2ee..05b894248b8e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java @@ -48,7 +48,7 @@ public abstract class ProjectManagerEx extends ProjectManager { public abstract boolean canClose(Project project); - public abstract void saveChangedProjectFile(@NotNull VirtualFile file, @Nullable Project project); + public abstract void saveChangedProjectFile(@NotNull VirtualFile file, @NotNull Project project); public abstract boolean isFileSavedToBeReloaded(VirtualFile file); diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index ff3977cf4be8..29cbe53511a6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -547,7 +547,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra private final ActionCallback myFocusedCallback; private final ActionCallback myTypeAheadDone; private final ActionCallback myTypeAheadCallback; - private MyComponentListener myComponentListener; public MyDialog(Window owner, DialogWrapper dialogWrapper, @@ -579,9 +578,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); myWindowListener = new MyWindowListener(); addWindowListener(myWindowListener); - - myComponentListener = new MyComponentListener(); - addComponentListener(myComponentListener); } @Override @@ -852,11 +848,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra myWindowListener = null; } - if (myComponentListener != null) { - removeComponentListener(myComponentListener); - myComponentListener = null; - } - if (myFocusTrackback != null && !(myFocusTrackback.isSheduledForRestore() || myFocusTrackback.isWillBeSheduledForRestore())) { myFocusTrackback.dispose(); myFocusTrackback = null; @@ -1035,20 +1026,12 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra } } - private class MyComponentListener extends ComponentAdapter { - @Override - @SuppressWarnings({"RefusedBequest"}) - public void componentResized(ComponentEvent e) { - if (getDialogWrapper().isAutoAdjustable()) { - UIUtil.adjustWindowToMinimumSize(getWindow()); - } - } - } - private class DialogRootPane extends JRootPane implements DataProvider { private final boolean myGlassPaneIsSet; + private Dimension myLastMinimumSize; + private DialogRootPane() { setGlassPane(new IdeGlassPaneImpl(this)); myGlassPaneIsSet = true; @@ -1062,6 +1045,31 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra return p; } + @Override + public void validate() { + super.validate(); + DialogWrapper wrapper = myDialogWrapper.get(); + if (wrapper != null && wrapper.isAutoAdjustable()) { + Window window = wrapper.getWindow(); + if (window != null) { + Dimension size = getMinimumSize(); + if (!(size == null ? myLastMinimumSize == null : size.equals(myLastMinimumSize))) { + // update window minimum size only if root pane minimum size is changed + if (size == null) { + myLastMinimumSize = null; + } + else { + myLastMinimumSize = new Dimension(size); + Insets insets = window.getInsets(); + size.width += insets.left + insets.right; + size.height += insets.top + insets.bottom; + } + window.setMinimumSize(size); + } + } + } + } + @Override public void setGlassPane(final Component glass) { if (myGlassPaneIsSet) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index bc898a49987b..7c35ffc56ff8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -316,6 +316,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { for (int i = 0; i < childrenIds.length; i++) { FSRecords.NameId child = childrenIds[i]; result[i] = child.id; + assert child.id > 0 : child; prevChildren.remove(child.id); if (VfsData.getFileById(child.id, this) == null) { createChild(child.nameId, child.id, delegate); @@ -426,6 +427,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { int i = -negativeIndex -1; System.arraycopy(array, 0, appended, 0, i); appended[i] = file.getId(); + assert appended[i] > 0 : file; System.arraycopy(array, i, appended, i + 1, array.length - i); myData.myChildrenIds = appended; } diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java index a9510359c76b..06b4a9ddcd70 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java @@ -140,7 +140,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, } public void setText(String text) { - setText(text, true); + setText(text, false); } @Override @@ -187,7 +187,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, } } - setText(myDocumentTextBuilder.toString(), false); + setText(myDocumentTextBuilder.toString(), true); } private static void appendAbbreviatedLine(StringBuilder to, String line, FontMetrics metrics, int maxWidth) { @@ -212,8 +212,10 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, } } - private void setText(String text, boolean updatePreferredSize) { - myEditor.getMarkupModel().removeAllHighlighters(); + private void setText(String text, boolean abbreviationOfCurrentText) { + if (!abbreviationOfCurrentText) { + myEditor.getMarkupModel().removeAllHighlighters(); + } myEditor.getDocument().setText(text); myEditor.getHighlighter().setText(text); @@ -222,7 +224,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, SelectionModel selectionModel = myEditor.getSelectionModel(); selectionModel.setSelection(0, selectionModel.hasSelection() ? myEditor.getDocument().getTextLength() : 0); - if (updatePreferredSize) { + if (!abbreviationOfCurrentText) { myPreferredSize = super.getPreferredSize(); } } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 3c01fdd78d53..7274d0930824 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -56,6 +56,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; +import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; import java.util.HashSet; @@ -901,7 +902,9 @@ public class AbstractPopup implements JBPopup { public void run() { if (myPreferredFocusedComponent != null && myInStack && myFocusable) { myFocusTrackback.registerFocusComponent(myPreferredFocusedComponent); - IJSwingUtilities.moveMousePointerOn(myPreferredFocusedComponent); + if (myPreferredFocusedComponent instanceof JTextComponent) { + IJSwingUtilities.moveMousePointerOn(myPreferredFocusedComponent); + } } removeActivity(); diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 2a5e8e94aed1..58bc65a31f6e 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -486,6 +486,8 @@ action.Forward.text=For_ward action.Forward.description=Redo last undone navigation operation action.JumpToLastChange.text=Last Edit L_ocation action.JumpToLastChange.description=Move through the most recent change points +action.JumpToNextChange.text=Next Edit Location +action.JumpToNextChange.description=Move through the most recent change points action.PreviousOccurence.text=Previ_ous Occurrence action.PreviousOccurence.description=Navigate to the previous occurrence action.NextOccurence.text=Ne_xt Occurrence diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml index 821cb528b6a9..ad6ab1b2ae1e 100644 --- a/platform/platform-resources/src/META-INF/xdebugger.xml +++ b/platform/platform-resources/src/META-INF/xdebugger.xml @@ -35,7 +35,7 @@ - + diff --git a/platform/platform-resources/src/checkedPlugins.txt b/platform/platform-resources/src/checkedPlugins.txt index 09653e9cdb5a..0d954d91cf4d 100644 --- a/platform/platform-resources/src/checkedPlugins.txt +++ b/platform/platform-resources/src/checkedPlugins.txt @@ -13,4 +13,5 @@ SBT JSTestDriver Plugin com.jetbrains.chronon AngularJS -org.jetbrains.plugins.vagrant \ No newline at end of file +org.jetbrains.plugins.vagrant +com.jetbrains.plugins.ini4idea \ No newline at end of file diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 7b4939d5e3b8..07a06b8300bb 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -108,7 +108,7 @@ - + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index a8fb31cc1833..956a90ea3c14 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -325,6 +325,7 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryFunctionalTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryFunctionalTest.java new file mode 100644 index 000000000000..29eb7629488d --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryFunctionalTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.fileEditor; + +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.testFramework.EditorTestUtil; + +public class IdeDocumentHistoryFunctionalTest extends HeavyFileEditorManagerTestCase { + public void testNavigateBetweenEditLocations() { + myFixture.configureByText(getTestName(false) + ".txt", + "line1\n" + + "\n" + + "\n" + + "\n" + + "line2\n" + + "\n" + + "\n" + + "\n" + + "line3"); + myFixture.type(' '); + moveCaret4LinesDown(); + myFixture.type(' '); + moveCaret4LinesDown(); + + EditorTestUtil.executeAction(getEditor(), IdeActions.ACTION_GOTO_LAST_CHANGE); + myFixture.checkResult(" line1\n" + + "\n" + + "\n" + + "\n" + + "l ine2\n" + + "\n" + + "\n" + + "\n" + + "line3"); + EditorTestUtil.executeAction(getEditor(), IdeActions.ACTION_GOTO_LAST_CHANGE); + myFixture.checkResult(" line1\n" + + "\n" + + "\n" + + "\n" + + "l ine2\n" + + "\n" + + "\n" + + "\n" + + "line3"); + EditorTestUtil.executeAction(getEditor(), IdeActions.ACTION_GOTO_NEXT_CHANGE); + myFixture.checkResult(" line1\n" + + "\n" + + "\n" + + "\n" + + "l ine2\n" + + "\n" + + "\n" + + "\n" + + "line3"); + EditorTestUtil.executeAction(getEditor(), IdeActions.ACTION_GOTO_NEXT_CHANGE); + myFixture.checkResult(" line1\n" + + "\n" + + "\n" + + "\n" + + "l ine2\n" + + "\n" + + "\n" + + "\n" + + "line3"); + } + + private void moveCaret4LinesDown() { + for (int i = 0; i < 4; i++) { + EditorTestUtil.executeAction(getEditor(), IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN); + } + } +} diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceCommand.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceCommand.java index ed5ebaaf4e2c..af0d230edbfb 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceCommand.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceCommand.java @@ -2,7 +2,10 @@ package com.intellij.structuralsearch.plugin.replace.ui; import com.intellij.structuralsearch.MatchResult; import com.intellij.structuralsearch.plugin.StructuralSearchPlugin; -import com.intellij.structuralsearch.plugin.ui.*; +import com.intellij.structuralsearch.plugin.ui.Configuration; +import com.intellij.structuralsearch.plugin.ui.SearchCommand; +import com.intellij.structuralsearch.plugin.ui.SearchContext; +import com.intellij.structuralsearch.plugin.ui.UsageViewContext; import com.intellij.usages.Usage; /** @@ -21,9 +24,9 @@ public class ReplaceCommand extends SearchCommand { } protected UsageViewContext createUsageViewContext() { - final SearchStarter searchStarter = new SearchStarter() { + final Runnable searchStarter = new Runnable() { @Override - public void startSearch() { + public void run() { new ReplaceCommand(myConfiguration, mySearchContext).startSearching(); } }; diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceUsageViewContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceUsageViewContext.java index 17618cb0fc53..7ef3a906906a 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceUsageViewContext.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/ui/ReplaceUsageViewContext.java @@ -10,7 +10,6 @@ import com.intellij.structuralsearch.plugin.replace.ReplacementInfo; import com.intellij.structuralsearch.plugin.replace.impl.Replacer; import com.intellij.structuralsearch.plugin.ui.Configuration; import com.intellij.structuralsearch.plugin.ui.SearchContext; -import com.intellij.structuralsearch.plugin.ui.SearchStarter; import com.intellij.structuralsearch.plugin.ui.UsageViewContext; import com.intellij.usageView.UsageInfo; import com.intellij.usages.Usage; @@ -32,7 +31,7 @@ class ReplaceUsageViewContext extends UsageViewContext { private final HashMap usage2ReplacementInfo = new HashMap(); private final Replacer replacer = new Replacer(mySearchContext.getProject(), ((ReplaceConfiguration)myConfiguration).getOptions()); - ReplaceUsageViewContext(SearchContext context, Configuration configuration, SearchStarter searchStarter) { + ReplaceUsageViewContext(SearchContext context, Configuration configuration, Runnable searchStarter) { super(configuration, context, searchStarter); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java index 83ae8d836386..d4c4c8247074 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java @@ -11,7 +11,6 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.util.AbstractProgressIndicatorExBase; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Factory; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.psi.PsiDocumentManager; @@ -46,9 +45,9 @@ public class SearchCommand { } protected UsageViewContext createUsageViewContext() { - final SearchStarter searchStarter = new SearchStarter() { + final Runnable searchStarter = new Runnable() { @Override - public void startSearch() { + public void run() { new SearchCommand(myConfiguration, mySearchContext).startSearching(); } }; diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchStarter.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchStarter.java deleted file mode 100644 index 457df61be46d..000000000000 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchStarter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.intellij.structuralsearch.plugin.ui; - -/** - * @author Bas Leijdekkers - */ -public interface SearchStarter { - - void startSearch(); -} diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java index db93e804b186..1f592e6cf534 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java @@ -11,7 +11,6 @@ import com.intellij.psi.PsiFile; import com.intellij.structuralsearch.MatchOptions; import com.intellij.structuralsearch.SSRBundle; import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration; -import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration; import com.intellij.usages.ConfigurableUsageTarget; import com.intellij.usages.Usage; import com.intellij.usages.UsageView; @@ -30,12 +29,12 @@ import java.util.Set; */ public class UsageViewContext { protected final SearchContext mySearchContext; - private final SearchStarter mySearchStarter; + private final Runnable mySearchStarter; private UsageView myUsageView; protected final Configuration myConfiguration; private Set myExcludedSet; - protected UsageViewContext(Configuration configuration, SearchContext searchContext, SearchStarter searchStarter) { + protected UsageViewContext(Configuration configuration, SearchContext searchContext, Runnable searchStarter) { myConfiguration = configuration; mySearchContext = searchContext; mySearchStarter = searchStarter; @@ -102,7 +101,7 @@ public class UsageViewContext { @Override public void findUsages() { - mySearchStarter.startSearch(); + mySearchStarter.run(); } @Override diff --git a/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java b/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java index c597eea48db0..ee4f0b63cc8a 100644 --- a/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java +++ b/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java @@ -28,7 +28,7 @@ import java.util.List; */ public class UsageViewPresentation { private String myTabText; - private String myScopeText; + private String myScopeText = ""; // Default value. to be overwritten in most cases. private String myUsagesString; private String myTargetsNodeText = UsageViewBundle.message("node.targets"); // Default value. to be overwritten in most cases. private String myNonCodeUsagesString = UsageViewBundle.message("node.non.code.usages"); diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index cb2073b1e0ce..3ac31010f867 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -338,7 +338,6 @@ search.everywhere.actions=true search.everywhere.configurations=true search.everywhere.settings=false -svn.use.terminal=false svn.use.incoming.optimization=false svn.executable.locale=C.UTF-8 svn.lowest.supported.format.for.command.line=1.7.0 diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index bc41f70e933a..4324deee35d4 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -415,17 +415,6 @@ public class FileUtil extends FileUtilRt { } public static boolean delete(@NotNull File file) { - if (SystemInfo.isWindows) { - File tempFile = findSequentNonexistentFile(file.getParentFile(), file.getName(), ""); - if (file.renameTo(tempFile)) { - file = tempFile; - } - } - - return doDelete(file); - } - - private static boolean doDelete(File file) { FileAttributes attributes = FileSystemUtil.getAttributes(file); if (attributes == null) return true; @@ -433,7 +422,7 @@ public class FileUtil extends FileUtilRt { File[] files = file.listFiles(); if (files != null) { for (File child : files) { - if (!doDelete(child)) return false; + if (!delete(child)) return false; } } } @@ -1539,4 +1528,10 @@ public class FileUtil extends FileUtilRt { public static boolean isRootPath(@NotNull String path) { return path.equals("/") || path.matches("[a-zA-Z]:[/\\\\]"); } + + public static boolean deleteWithRenaming(File file) { + File tempFileNameForDeletion = findSequentNonexistentFile(file.getParentFile(), file.getName(), ""); + boolean success = file.renameTo(tempFileNameForDeletion); + return delete(success ? tempFileNameForDeletion:file); + } } diff --git a/platform/util/src/com/intellij/ui/TableUtil.java b/platform/util/src/com/intellij/ui/TableUtil.java index 28aa8d96e24c..25aae882205f 100644 --- a/platform/util/src/com/intellij/ui/TableUtil.java +++ b/platform/util/src/com/intellij/ui/TableUtil.java @@ -114,8 +114,9 @@ public class TableUtil { TableModel model = table.getModel(); boolean removed = false; for (int index = maxSelectionIndex; index >= 0; index--) { - if (selectionModel.isSelectedIndex(index) && (applyable == null || applyable.isOperationApplyable(model, index))) { - itemRemovable.removeRow(index); + int modelIndex = table.convertRowIndexToModel(index); + if (selectionModel.isSelectedIndex(index) && (applyable == null || applyable.isOperationApplyable(model, modelIndex))) { + itemRemovable.removeRow(modelIndex); removed = true; } } diff --git a/platform/util/src/com/intellij/util/SmartList.java b/platform/util/src/com/intellij/util/SmartList.java index 207c132473d2..775b63e8e887 100644 --- a/platform/util/src/com/intellij/util/SmartList.java +++ b/platform/util/src/com/intellij/util/SmartList.java @@ -236,7 +236,7 @@ public class SmartList extends AbstractList { } } - public void sort(@NotNull Comparator comparator) { + public void sort(Comparator comparator) { if (mySize >= 2) { Arrays.sort((E[])myElem, 0, mySize, comparator); } diff --git a/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java b/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java index 012437a96799..b0844695369a 100644 --- a/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/AbstractCollectionBinding.java @@ -115,11 +115,10 @@ abstract class AbstractCollectionBinding implements Binding { final String tagName = getTagName(o); if (tagName != null) { - if (ContainerUtil.isEmpty(collection)) { - return context == null ? new Element(tagName) : null; - } - Element result = new Element(tagName); + if (ContainerUtil.isEmpty(collection)) { + return new Element(tagName); + } for (Object e : collection) { if (e == null) { throw new XmlSerializationException("Collection " + myAccessor + " contains 'null' object"); diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index d0027edc0696..478462769023 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -76,11 +76,12 @@ class BeanBinding implements Binding { @Override @Nullable public Object serialize(@NotNull Object o, @Nullable Object context, SerializationFilter filter) { - return serializeInto(o, context == null ? new Element(myTagName) : null, filter); + Element element = new Element(myTagName); + serializeInto(o, element, filter); + return element; } - @Nullable - public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter) { + public void serializeInto(@NotNull Object o, @NotNull Element element, @NotNull SerializationFilter filter) { for (Binding binding : myPropertyBindingsList) { Accessor accessor = myPropertyBindings.get(binding); if (!filter.accepts(accessor, o)) continue; @@ -99,22 +100,16 @@ class BeanBinding implements Binding { } } - if (element == null) { - element = new Element(myTagName); - } - Object node = binding.serialize(o, element, filter); - if (node != null && node != element) { + if (node != null) { if (node instanceof org.jdom.Attribute) { - org.jdom.Attribute attr = (org.jdom.Attribute)node; - element.setAttribute(attr.getName(), attr.getValue()); + element.setAttribute((org.jdom.Attribute)node); } else { JDOMUtil.addContent(element, node); } } } - return element; } public void deserializeInto(final Object bean, @NotNull Element element) { diff --git a/platform/util/src/com/intellij/util/xmlb/JDOMElementBinding.java b/platform/util/src/com/intellij/util/xmlb/JDOMElementBinding.java index 41ae99f8557f..825c184e935c 100644 --- a/platform/util/src/com/intellij/util/xmlb/JDOMElementBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/JDOMElementBinding.java @@ -38,18 +38,19 @@ class JDOMElementBinding implements Binding { public Object serialize(Object o, Object context, SerializationFilter filter) { Object value = myAccessor.read(o); if (value == null) { - return context; + return null; } + if (value instanceof Element) { - Element targetElement; - targetElement = (Element)((Element)value).clone(); + Element targetElement = ((Element)value).clone(); + assert targetElement != null; targetElement.setName(myTagName); return targetElement; } if (value instanceof Element[]) { ArrayList result = new ArrayList(); for (Element element : ((Element[])value)) { - Element target = ((Element)element.clone()).setName(myTagName); + Element target = element.clone().setName(myTagName); result.add(target); } diff --git a/platform/util/src/com/intellij/util/xmlb/MapBinding.java b/platform/util/src/com/intellij/util/xmlb/MapBinding.java index 4c93669ccbe4..6783d88568e1 100644 --- a/platform/util/src/com/intellij/util/xmlb/MapBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/MapBinding.java @@ -31,7 +31,6 @@ import java.lang.reflect.Type; import java.util.Arrays; import java.util.Comparator; import java.util.Map; -import java.util.Set; import static com.intellij.util.xmlb.Constants.*; @@ -72,9 +71,7 @@ class MapBinding implements Binding { Element m = myMapAnnotation == null || myMapAnnotation.surroundWithTag() ? new Element(MAP) : (Element)context; assert m != null; - final Set keySet = map.keySet(); - final Object[] keys = ArrayUtil.toObjectArray(keySet); - + final Object[] keys = ArrayUtil.toObjectArray(map.keySet()); if (myMapAnnotation == null || myMapAnnotation.sortBeforeSave()) { Arrays.sort(keys, KEY_COMPARATOR); } @@ -89,7 +86,7 @@ class MapBinding implements Binding { if (kNode instanceof Text) { entry.setAttribute(getKeyAttributeName(), ((Text)kNode).getText()); } - else { + else if (kNode != null) { if (myMapAnnotation != null && !myMapAnnotation.surroundKeyWithTag()) { entry.addContent((Content)kNode); } @@ -104,7 +101,7 @@ class MapBinding implements Binding { if (vNode instanceof Text) { entry.setAttribute(getValueAttributeName(), ((Text)vNode).getText()); } - else { + else if (vNode != null) { if (myMapAnnotation != null && !myMapAnnotation.surroundValueWithTag()) { entry.addContent((Element)vNode); } @@ -116,7 +113,7 @@ class MapBinding implements Binding { } } - return m; + return m == context ? null : m; } private String getEntryAttributeName() { @@ -167,15 +164,12 @@ class MapBinding implements Binding { } else { if (myMapAnnotation != null && !myMapAnnotation.surroundKeyWithTag()) { - final Object[] children = JDOMUtil.getContent(entry); - for (Object child : children) { + for (Object child : JDOMUtil.getContent(entry)) { if (myKeyBinding.isBoundTo(child)) { k = myKeyBinding.deserialize(o, child); break; } } - - assert k != null : "no key found"; } else { final Object keyNode = entry.getChildren(getKeyAttributeName()).get(0); @@ -189,15 +183,12 @@ class MapBinding implements Binding { } else { if (myMapAnnotation != null && !myMapAnnotation.surroundValueWithTag()) { - final Object[] children = JDOMUtil.getContent(entry); - for (Object child : children) { + for (Object child : JDOMUtil.getContent(entry)) { if (myValueBinding.isBoundTo(child)) { v = myValueBinding.deserialize(o, child); break; } } - - assert v != null : "no value found"; } else { final Object valueNode = entry.getChildren(getValueAttributeName()).get(0); diff --git a/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java b/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java index 6eca99793aab..d7a14bb32dae 100644 --- a/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java @@ -74,19 +74,16 @@ class OptionTagBinding extends BasePrimitiveBinding { else { assert myBinding != null; Object node = myBinding.serialize(value, targetElement, filter); - if (node == null) { - return context == null ? targetElement : null; - } - - if (node instanceof Text) { - Text text = (Text)node; - targetElement.setAttribute(myValueAttribute, text.getText()); - } - else if (targetElement != node) { - JDOMUtil.addContent(targetElement, node); + if (node != null) { + if (node instanceof Text) { + Text text = (Text)node; + targetElement.setAttribute(myValueAttribute, text.getText()); + } + else if (targetElement != node) { + JDOMUtil.addContent(targetElement, node); + } } } - return targetElement; } diff --git a/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java b/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java index f933695e9fa6..15ebb2d5c4b1 100644 --- a/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.util.xmlb; import com.intellij.openapi.util.JDOMUtil; @@ -37,8 +36,6 @@ class PrimitiveValueBinding implements Binding { @Override @Nullable public Object deserialize(Object o, @NotNull Object... nodes) { - assert nodes != null; - if (nodes.length == 0) { return convertString(""); } diff --git a/platform/util/src/com/intellij/util/xmlb/TagBinding.java b/platform/util/src/com/intellij/util/xmlb/TagBinding.java index 0743e247f2a2..289f9eeeb50b 100644 --- a/platform/util/src/com/intellij/util/xmlb/TagBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/TagBinding.java @@ -48,10 +48,7 @@ class TagBinding extends BasePrimitiveBinding { assert myBinding != null; Object node = myBinding.serialize(value, v, filter); - if (node != v) { - if (node == null) { - return context == null ? v : null; - } + if (node != null && node != v) { JDOMUtil.addContent(v, node); } return v; diff --git a/platform/util/src/com/intellij/util/xmlb/TagBindingWrapper.java b/platform/util/src/com/intellij/util/xmlb/TagBindingWrapper.java index 09f50d6e451a..389adca9cd18 100644 --- a/platform/util/src/com/intellij/util/xmlb/TagBindingWrapper.java +++ b/platform/util/src/com/intellij/util/xmlb/TagBindingWrapper.java @@ -41,17 +41,17 @@ class TagBindingWrapper implements Binding { @Override public Object serialize(Object o, @Nullable Object context, SerializationFilter filter) { Element e = new Element(myTagName); - Content n = (Content)binding.serialize(o, e, filter); - if (n == null) { - return null; - } - - String value = n.getValue(); - if (!myAttributeName.isEmpty()) { - e.setAttribute(myAttributeName, value); - } - else { - e.addContent(new Text(value)); + Content content = (Content)binding.serialize(o, e, filter); + if (content != null) { + if (!myAttributeName.isEmpty()) { + e.setAttribute(myAttributeName, content.getValue()); + } + else if (content instanceof Text) { + e.addContent(content); + } + else { + e.addContent(content.getValue()); + } } return e; } diff --git a/platform/util/src/com/intellij/util/xmlb/TextBinding.java b/platform/util/src/com/intellij/util/xmlb/TextBinding.java index c657c9f754d4..5cfaad76594d 100644 --- a/platform/util/src/com/intellij/util/xmlb/TextBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/TextBinding.java @@ -37,7 +37,15 @@ public class TextBinding implements Binding { return null; } Object node = myBinding.serialize(v, context, filter); - return node == null ? null : new Text(((Content)node).getValue()); + if (node == null) { + return null; + } + else if (node instanceof Text) { + return node; + } + else { + return new Text(((Content)node).getValue()); + } } @Override diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index eea800de8a2e..0f7217c5241e 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -126,6 +126,9 @@ public class XmlSerializerTest extends TestCase { BeanWithSubBean bean = new BeanWithSubBean(); doSerializerTest( "\n" + + " \n" + "