From e70f10ded2d5c2c059f20f586691e279eb1b816d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 21 Oct 2009 19:22:42 +0400 Subject: [PATCH] IDEADEV-8718 --- .../options/CodeStyleImportsPanel.java | 464 ++++++++---------- .../options/JavaIndentOptionsEditor.java | 3 +- .../impl/source/codeStyle/ImportHelper.java | 223 ++++----- .../options/IndentOptionsEditor.java | 5 +- .../options/SmartIndentOptionsEditor.java | 3 +- .../psi/codeStyle/CodeStyleSettings.java | 450 +++-------------- .../intellij/psi/codeStyle/PackageEntry.java | 114 +++++ .../psi/codeStyle/PackageEntryTable.java | 166 +++++++ .../options/GeneralCodeStylePanel.java | 45 +- .../intellij/ui/BooleanTableCellRenderer.java | 5 +- .../openapi/util/DefaultJDOMExternalizer.java | 14 +- .../openapi/util/text/StringUtil.java | 15 +- .../intellij/util/containers/ClassMap.java | 6 +- 13 files changed, 734 insertions(+), 779 deletions(-) create mode 100755 platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java create mode 100755 platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java b/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java index 52c45d7d6570..7cea048cd910 100644 --- a/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java +++ b/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java @@ -16,21 +16,24 @@ package com.intellij.application.options; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.editor.SyntaxHighlighterColors; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.ui.ex.MultiLineLabel; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.PackageEntry; +import com.intellij.psi.codeStyle.PackageEntryTable; import com.intellij.ui.*; import com.intellij.util.ui.Table; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.TableCellEditor; -import javax.swing.table.TableModel; +import javax.swing.event.*; +import javax.swing.table.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; public class CodeStyleImportsPanel extends JPanel { private JCheckBox myCbUseFQClassNames; @@ -41,9 +44,8 @@ public class CodeStyleImportsPanel extends JPanel { private JCheckBox myCbAddUnambiguousImportsOnTheFly; private JTextField myClassCountField; private JTextField myNamesCountField; - private final CodeStyleSettings.ImportLayoutTable myImportLayoutList = new CodeStyleSettings.ImportLayoutTable(); - private CodeStyleSettings.PackageTable myPackageList = new CodeStyleSettings.PackageTable(); - private CodeStyleSettings.ImportLayoutTable.PackageEntry myOtherPackageEntry = null; + private final PackageEntryTable myImportLayoutList = new PackageEntryTable(); + private final PackageEntryTable myPackageList = new PackageEntryTable(); private Table myImportLayoutTable; private JButton myMoveUpButton; @@ -60,6 +62,7 @@ public class CodeStyleImportsPanel extends JPanel { private JPanel myPackagesPanel; private JPanel myImportsLayoutPanel; private JPanel myWholePanel; + private JCheckBox myCbLayoutStaticImportsSeparately; public CodeStyleImportsPanel(CodeStyleSettings settings){ mySettings = settings; @@ -69,8 +72,8 @@ public class CodeStyleImportsPanel extends JPanel { myGeneralPanel.add(createGeneralOptionsPanel(), BorderLayout.CENTER); myJSPPanel.add(createJspImportLayoutPanel(), BorderLayout.CENTER); - myPackagesPanel.add(createPackagesPanel(), BorderLayout.NORTH); myImportsLayoutPanel.add(createImportLayoutPanel(), BorderLayout.NORTH); + myPackagesPanel.add(createPackagesPanel(), BorderLayout.NORTH); } private JPanel createJspImportLayoutPanel() { @@ -157,12 +160,57 @@ public class CodeStyleImportsPanel extends JPanel { private JPanel createImportLayoutPanel() { JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("title.import.layout"))); + myCbLayoutStaticImportsSeparately = new JCheckBox("Layout static imports separately"); + + myCbLayoutStaticImportsSeparately.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if (areStaticImportsEnabled()) { + boolean found = false; + for (int i=myImportLayoutList.getEntryCount()-1; i>=0; i--) { + PackageEntry entry = myImportLayoutList.getEntryAt(i); + if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) { + found = true; + break; + } + } + if (!found) { + int index = myImportLayoutList.getEntryCount(); + if (index != 0 && myImportLayoutList.getEntryAt(index-1) != PackageEntry.BLANK_LINE_ENTRY) { + myImportLayoutList.addEntry(PackageEntry.BLANK_LINE_ENTRY); + } + myImportLayoutList.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY); + } + } + else { + for (int i=myImportLayoutList.getEntryCount()-1; i>=0; i--) { + PackageEntry entry = myImportLayoutList.getEntryAt(i); + if (entry.isStatic()) { + myImportLayoutList.removeEntryAt(i); + } + } + } + refreshTable(myImportLayoutTable, myImportLayoutList); + refreshTable(myPackageTable, myPackageList); + } + }); + panel.add(myCbLayoutStaticImportsSeparately, BorderLayout.NORTH); panel.add(createImportLayoutTable(), BorderLayout.CENTER); panel.add(createImportLayoutButtonsPanel(), BorderLayout.EAST); panel.setPreferredSize(new Dimension(-1, 200)); return panel; } + private void refreshTable(final Table table, final PackageEntryTable packageTable) { + AbstractTableModel model = (AbstractTableModel)table.getModel(); + table.createDefaultColumnsFromModel(); + model.fireTableDataChanged(); + resizeColumns(packageTable, table); + } + + private boolean areStaticImportsEnabled() { + return myCbLayoutStaticImportsSeparately.isSelected(); + } + private JPanel createImportLayoutButtonsPanel() { JPanel tableButtonsPanel = new JPanel(new VerticalFlowLayout()); @@ -258,7 +306,7 @@ public class CodeStyleImportsPanel extends JPanel { if(selected < 0) { selected = myImportLayoutList.getEntryCount(); } - CodeStyleSettings.ImportLayoutTable.PackageEntry entry = new CodeStyleSettings.ImportLayoutTable.PackageEntry("", true); + PackageEntry entry = new PackageEntry(false,"", true); myImportLayoutList.insertEntryAt(entry, selected); refreshTableModel(selected, myImportLayoutTable); } @@ -267,8 +315,6 @@ public class CodeStyleImportsPanel extends JPanel { AbstractTableModel model = (AbstractTableModel)table.getModel(); model.fireTableRowsInserted(selectedRow, selectedRow); table.setRowSelectionInterval(selectedRow, selectedRow); -// myImportLayoutTable.requestFocus(); -// myImportLayoutTable.editCellAt(selected, 0); TableUtil.editCellAt(table, selectedRow, 0); Component editorComp = table.getEditorComponent(); if(editorComp != null) { @@ -281,7 +327,7 @@ public class CodeStyleImportsPanel extends JPanel { if(selected < 0) { selected = myPackageList.getEntryCount(); } - CodeStyleSettings.PackageTable.Entry entry = new CodeStyleSettings.PackageTable.Entry("", true); + PackageEntry entry = new PackageEntry(false,"", true); myPackageList.insertEntryAt(entry, selected); refreshTableModel(selected, myPackageTable); } @@ -291,8 +337,7 @@ public class CodeStyleImportsPanel extends JPanel { if(selected < 0) { selected = myImportLayoutList.getEntryCount(); } - CodeStyleSettings.ImportLayoutTable.EmptyLineEntry entry = new CodeStyleSettings.ImportLayoutTable.EmptyLineEntry(); - myImportLayoutList.insertEntryAt(entry, selected); + myImportLayoutList.insertEntryAt(PackageEntry.BLANK_LINE_ENTRY, selected); AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel(); model.fireTableRowsInserted(selected, selected); myImportLayoutTable.setRowSelectionInterval(selected, selected); @@ -302,26 +347,11 @@ public class CodeStyleImportsPanel extends JPanel { int selected = myImportLayoutTable.getSelectedRow(); if(selected < 0) return; - CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(selected); - if(isOtherEntry(entry)) { - boolean isFound = false; - CodeStyleSettings.ImportLayoutTable.Entry[] entries = myImportLayoutList.getEntries(); - for(int i = 0; i < entries.length; i++){ - if(i != selected && isOtherEntry(entries[i])) { - isFound = true; - break; - } - } - if(!isFound) { - return; - } - } - if(myImportLayoutTable.isEditing()) { - TableCellEditor editor = myImportLayoutTable.getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); - } + PackageEntry entry = myImportLayoutList.getEntryAt(selected); + if(entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY) { + return; } + TableUtil.stopEditing(myImportLayoutTable); myImportLayoutList.removeEntryAt(selected); AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel(); model.fireTableRowsDeleted(selected, selected); @@ -335,14 +365,8 @@ public class CodeStyleImportsPanel extends JPanel { private void removeEntryFromPackages() { int selected = myPackageTable.getSelectedRow(); - if(selected < 0) - return; - if(myPackageTable.isEditing()) { - TableCellEditor editor = myPackageTable.getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); - } - } + if(selected < 0) return; + TableUtil.stopEditing(myPackageTable); myPackageList.removeEntryAt(selected); AbstractTableModel model = (AbstractTableModel)myPackageTable.getModel(); model.fireTableRowsDeleted(selected, selected); @@ -359,14 +383,9 @@ public class CodeStyleImportsPanel extends JPanel { if(selected < 1) { return; } - if(myImportLayoutTable.isEditing()) { - TableCellEditor editor = myImportLayoutTable.getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); - } - } - CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(selected); - CodeStyleSettings.ImportLayoutTable.Entry previousEntry = myImportLayoutList.getEntryAt(selected-1); + TableUtil.stopEditing(myImportLayoutTable); + PackageEntry entry = myImportLayoutList.getEntryAt(selected); + PackageEntry previousEntry = myImportLayoutList.getEntryAt(selected-1); myImportLayoutList.setEntryAt(previousEntry, selected); myImportLayoutList.setEntryAt(entry, selected-1); @@ -380,14 +399,9 @@ public class CodeStyleImportsPanel extends JPanel { if(selected >= myImportLayoutList.getEntryCount()-1) { return; } - if(myImportLayoutTable.isEditing()) { - TableCellEditor editor = myImportLayoutTable.getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); - } - } - CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(selected); - CodeStyleSettings.ImportLayoutTable.Entry nextEntry = myImportLayoutList.getEntryAt(selected+1); + TableUtil.stopEditing(myImportLayoutTable); + PackageEntry entry = myImportLayoutList.getEntryAt(selected); + PackageEntry nextEntry = myImportLayoutList.getEntryAt(selected+1); myImportLayoutList.setEntryAt(nextEntry, selected); myImportLayoutList.setEntryAt(entry, selected+1); @@ -397,66 +411,110 @@ public class CodeStyleImportsPanel extends JPanel { } private JComponent createPackagesTable() { + myPackageTable = createTableForPackageEntries(myPackageList); + return ScrollPaneFactory.createScrollPane(myPackageTable); + } + + private Table createTableForPackageEntries(final PackageEntryTable packageTable) { final String[] names = { ApplicationBundle.message("listbox.import.package"), - ApplicationBundle.message("listbox.import.with.subpackages") + ApplicationBundle.message("listbox.import.with.subpackages"), }; // Create a model of the data. TableModel dataModel = new AbstractTableModel() { - public int getColumnCount() { return names.length; } - public int getRowCount() { return myPackageList.getEntryCount();} - public Object getValueAt(int row, int col) { - CodeStyleSettings.PackageTable.Entry entry = myPackageList.getEntryAt(row); - if(col == 0) { - if(entry != null) { - return entry.getPackageName(); - } - } - - if(col == 1) { - if(entry != null) { - return entry.isWithSubpackages() ? Boolean.TRUE : Boolean.FALSE; - } - } - return null; + public int getColumnCount() { + return names.length + (areStaticImportsEnabled()?1:0); } - public String getColumnName(int column) { return names[column]; } - public Class getColumnClass(int c) { - if(c == 0) { - return String.class; + + public int getRowCount() { + return packageTable.getEntryCount(); + } + + public Object getValueAt(int row, int col) { + PackageEntry entry = packageTable.getEntryAt(row); + if (entry == null || !isCellEditable(row, col)) return null; + col += areStaticImportsEnabled() ? 0 : 1; + if(col == 0) { + return entry.isStatic(); } - if(c == 1) { + if(col == 1) { + return entry.getPackageName(); + } + if(col == 2) { + return entry.isWithSubpackages() ? Boolean.TRUE : Boolean.FALSE; + } + throw new IllegalArgumentException(String.valueOf(col)); + } + + public String getColumnName(int column) { + if (areStaticImportsEnabled() && column == 0) return "Static"; + column -= areStaticImportsEnabled() ? 1 : 0; + return names[column]; + } + + public Class getColumnClass(int col) { + col += areStaticImportsEnabled() ? 0 : 1; + if(col == 0) { return Boolean.class; } - return null; + if(col == 1) { + return String.class; + } + if(col == 2) { + return Boolean.class; + } + throw new IllegalArgumentException(String.valueOf(col)); } + public boolean isCellEditable(int row, int col) { - return true; + PackageEntry packageEntry = packageTable.getEntryAt(row); + return !packageEntry.isSpecial(); } public void setValueAt(Object aValue, int row, int col) { - CodeStyleSettings.PackageTable.Entry packageEntry = myPackageList.getEntryAt(row); + PackageEntry packageEntry = packageTable.getEntryAt(row); + col += areStaticImportsEnabled() ? 0 : 1; if(col == 0) { - CodeStyleSettings.PackageTable.Entry newPackageEntry = new CodeStyleSettings.PackageTable.Entry(((String)aValue).trim(), packageEntry.isWithSubpackages()); - myPackageList.setEntryAt(newPackageEntry, row); + PackageEntry newPackageEntry = new PackageEntry((Boolean)aValue, packageEntry.getPackageName(), packageEntry.isWithSubpackages()); + packageTable.setEntryAt(newPackageEntry, row); } - - if(col == 1) { - CodeStyleSettings.PackageTable.Entry newPackageEntry = new CodeStyleSettings.PackageTable.Entry(packageEntry.getPackageName(), ((Boolean)aValue).booleanValue()); - myPackageList.setEntryAt(newPackageEntry, row); + else if(col == 1) { + PackageEntry newPackageEntry = new PackageEntry(packageEntry.isStatic(), ((String)aValue).trim(), packageEntry.isWithSubpackages()); + packageTable.setEntryAt(newPackageEntry, row); + } + else if(col == 2) { + PackageEntry newPackageEntry = new PackageEntry(packageEntry.isStatic(), packageEntry.getPackageName(), ((Boolean)aValue).booleanValue()); + packageTable.setEntryAt(newPackageEntry, row); + } + else { + throw new IllegalArgumentException(String.valueOf(col)); } } }; // Create the table - myPackageTable = new Table(dataModel); - myPackageTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - TableCellEditor editor = myPackageTable.getDefaultEditor(String.class); - myPackageTable.fixColumnWidthToHeader(1); + final Table result = new Table(dataModel); + result.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + resizeColumns(packageTable, result); + + TableCellEditor editor = result.getDefaultEditor(String.class); if (editor instanceof DefaultCellEditor) { ((DefaultCellEditor)editor).setClickCountToStart(1); } - myPackageTable.getSelectionModel().addListSelectionListener( + + TableCellEditor beditor = result.getDefaultEditor(Boolean.class); + beditor.addCellEditorListener(new CellEditorListener() { + public void editingStopped(ChangeEvent e) { + if (areStaticImportsEnabled()) { + result.repaint(); // add/remove static keyword + } + } + + public void editingCanceled(ChangeEvent e) { + } + }); + + result.getSelectionModel().addListSelectionListener( new ListSelectionListener(){ public void valueChanged(ListSelectionEvent e){ updateButtons(); @@ -464,124 +522,64 @@ public class CodeStyleImportsPanel extends JPanel { } ); - return ScrollPaneFactory.createScrollPane(myPackageTable); + return result; + } + + private void resizeColumns(final PackageEntryTable packageTable, Table result) { + ColoredTableCellRenderer packageRenderer = new ColoredTableCellRenderer() { + @Override + protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) { + PackageEntry entry = packageTable.getEntryAt(row); + + if (entry == PackageEntry.BLANK_LINE_ENTRY) { + append(" ", SimpleTextAttributes.LINK_ATTRIBUTES); + } + else { + TextAttributes attributes = SyntaxHighlighterColors.KEYWORD.getDefaultAttributes(); + append("import", SimpleTextAttributes.fromTextAttributes(attributes)); + if (entry.isStatic()) { + append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES); + append("static", SimpleTextAttributes.fromTextAttributes(attributes)); + } + append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES); + + if (entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) { + append("all other imports", SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + else { + append(entry.getPackageName() + ".*", SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + } + } + }; + if (areStaticImportsEnabled()) { + result.fixColumnWidthToHeader(0); + result.fixColumnWidthToHeader(2); + result.getColumnModel().getColumn(1).setCellRenderer(packageRenderer); + result.getColumnModel().getColumn(0).setCellRenderer(new BooleanTableCellRenderer()); + result.getColumnModel().getColumn(2).setCellRenderer(new BooleanTableCellRenderer()); + } + else { + result.fixColumnWidthToHeader(1); + result.getColumnModel().getColumn(0).setCellRenderer(packageRenderer); + result.getColumnModel().getColumn(1).setCellRenderer(new BooleanTableCellRenderer()); + } } private void updateButtons(){ int selectedImport = myImportLayoutTable.getSelectedRow(); myMoveUpButton.setEnabled(selectedImport >= 1); myMoveDownButton.setEnabled(selectedImport < myImportLayoutTable.getRowCount()-1); - if(selectedImport < 0 || myOtherPackageEntry == myImportLayoutList.getEntryAt(selectedImport)) { - myRemovePackageFromImportLayoutButton.setEnabled(false); - } - else { - myRemovePackageFromImportLayoutButton.setEnabled(true); - } + PackageEntry entry = selectedImport < 0 ? null : myImportLayoutList.getEntryAt(selectedImport); + boolean canRemove = entry != null && entry != PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY && entry != PackageEntry.ALL_OTHER_IMPORTS_ENTRY; + myRemovePackageFromImportLayoutButton.setEnabled(canRemove); int selectedPackage = myPackageTable.getSelectedRow(); myRemovePackageFromPackagesButton.setEnabled(selectedPackage >= 0); - - } - - private static boolean isOtherEntry(CodeStyleSettings.ImportLayoutTable.Entry entry) { - if(!(entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry)) { - return false; - } - CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry; - String packageName = packageEntry.getPackageName(); - return packageName.length() == 0 && packageEntry.isWithSubpackages(); } private JComponent createImportLayoutTable() { - final String[] names = { - ApplicationBundle.message("listbox.import.package"), - ApplicationBundle.message("listbox.import.with.subpackages") - }; - // Create a model of the data. - TableModel dataModel = new AbstractTableModel() { - public int getColumnCount() { return names.length; } - public int getRowCount() { return myImportLayoutList.getEntryCount();} - public Object getValueAt(int row, int col) { - CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(row); - if(col == 0) { - if(isOtherEntry(entry) && entry == myOtherPackageEntry) { - return ApplicationBundle.message("listbox.import.all.other.imports"); - } - else if(entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) { - CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry; - return packageEntry.getPackageName(); - } - else { - return ApplicationBundle.message("listbox.import.blank.line"); - } - } - - if(col == 1) { - if(isOtherEntry(entry) && entry == myOtherPackageEntry) { - return null; - } - else if(entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) { - CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry; - return packageEntry.isWithSubpackages() ? Boolean.TRUE : Boolean.FALSE; - } - else { - return null; - } - } - return null; - } - public String getColumnName(int column) { return names[column]; } - public Class getColumnClass(int c) { - if(c == 0) { - return String.class; - } - if(c == 1) { - return Boolean.class; - } - return null; -// return CodeStyleSettings.ImportLayoutTable.Entry.class; - } - public boolean isCellEditable(int row, int col) { - CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(row); - if (isOtherEntry(entry) && entry == myOtherPackageEntry) { - return false; - } - return entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry; - } - - public void setValueAt(Object aValue, int row, int col) { - CodeStyleSettings.ImportLayoutTable.Entry entry = myImportLayoutList.getEntryAt(row); - if(col == 0 && entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) { - CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry; - CodeStyleSettings.ImportLayoutTable.PackageEntry newPackageEntry = new CodeStyleSettings.ImportLayoutTable.PackageEntry(((String)aValue).trim(), packageEntry.isWithSubpackages()); - myImportLayoutList.setEntryAt(newPackageEntry, row); - } - if(col == 1 && entry instanceof CodeStyleSettings.ImportLayoutTable.PackageEntry) { - CodeStyleSettings.ImportLayoutTable.PackageEntry packageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry; - CodeStyleSettings.ImportLayoutTable.PackageEntry newPackageEntry = new CodeStyleSettings.ImportLayoutTable.PackageEntry(packageEntry.getPackageName(), aValue.equals(Boolean.TRUE)); - myImportLayoutList.setEntryAt(newPackageEntry, row); - } - } - }; - - // Create the table - myImportLayoutTable = new Table(dataModel); - myImportLayoutTable.setDefaultRenderer(Boolean.class, new BooleanTableCellRenderer()); - myImportLayoutTable.fixColumnWidthToHeader(1); - myImportLayoutTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - TableCellEditor editor = myImportLayoutTable.getDefaultEditor(String.class); - if (editor instanceof DefaultCellEditor) { - ((DefaultCellEditor)editor).setClickCountToStart(1); - } - - myImportLayoutTable.getSelectionModel().addListSelectionListener( - new ListSelectionListener(){ - public void valueChanged(ListSelectionEvent e){ - updateButtons(); - } - } - ); - + myImportLayoutTable = createTableForPackageEntries(myImportLayoutList); return ScrollPaneFactory.createScrollPane(myImportLayoutTable); } @@ -596,14 +594,9 @@ public class CodeStyleImportsPanel extends JPanel { myCbOptimizeImportsOnTheFly.setSelected(mySettings.OPTIMIZE_IMPORTS_ON_THE_FLY); myImportLayoutList.copyFrom(mySettings.IMPORT_LAYOUT_TABLE); - CodeStyleSettings.ImportLayoutTable.Entry[] entries = myImportLayoutList.getEntries(); - for (CodeStyleSettings.ImportLayoutTable.Entry entry : entries) { - if (isOtherEntry(entry)) { - myOtherPackageEntry = (CodeStyleSettings.ImportLayoutTable.PackageEntry)entry; - } - } - myPackageList = new CodeStyleSettings.PackageTable(); myPackageList.copyFrom(mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND); + + myCbLayoutStaticImportsSeparately.setSelected(mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY); AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel(); model.fireTableDataChanged(); @@ -630,6 +623,7 @@ public class CodeStyleImportsPanel extends JPanel { public void apply() { stopTableEditing(); + mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY = areStaticImportsEnabled(); mySettings.USE_FQ_CLASS_NAMES = myCbUseFQClassNames.isSelected(); mySettings.USE_FQ_CLASS_NAMES_IN_JAVADOC = myCbUseFQClassNamesInJavaDoc.isSelected(); mySettings.USE_SINGLE_CLASS_IMPORTS = myCbUseSingleClassImports.isSelected(); @@ -649,41 +643,25 @@ public class CodeStyleImportsPanel extends JPanel { //just a bad number } + myImportLayoutList.removeEmptyPackages(); mySettings.IMPORT_LAYOUT_TABLE.copyFrom(myImportLayoutList); - CodeStyleSettings.ImportLayoutTable.Entry[] entries = myImportLayoutList.getEntries(); - int removedEntryCount = 0; - for(int i = 0; i < entries.length; i++){ - CodeStyleSettings.ImportLayoutTable.Entry entry = entries[i]; - if(isOtherEntry(entry) && entry != myOtherPackageEntry) { - mySettings.IMPORT_LAYOUT_TABLE.removeEntryAt(i-removedEntryCount); - removedEntryCount++; - } - } - - mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND = myPackageList; + myPackageList.removeEmptyPackages(); + mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(myPackageList); mySettings.JSP_PREFER_COMMA_SEPARATED_IMPORT_LIST = myJspImportCommaSeparated.isSelected(); } + private void stopTableEditing() { - if(myImportLayoutTable.isEditing()) { - TableCellEditor editor = myImportLayoutTable.getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); - } - } - if(myPackageTable.isEditing()) { - TableCellEditor editor = myPackageTable.getCellEditor(); - if (editor != null) { - editor.stopCellEditing(); - } - } + TableUtil.stopEditing(myImportLayoutTable); + TableUtil.stopEditing(myPackageTable); } public boolean isModified() { - - boolean isModified = isModified(myCbUseFQClassNames, mySettings.USE_FQ_CLASS_NAMES); + boolean + isModified = isModified(myCbLayoutStaticImportsSeparately, mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY); + isModified |= isModified(myCbUseFQClassNames, mySettings.USE_FQ_CLASS_NAMES); isModified |= isModified(myCbUseFQClassNamesInJavaDoc, mySettings.USE_FQ_CLASS_NAMES_IN_JAVADOC); isModified |= isModified(myCbUseSingleClassImports, mySettings.USE_SINGLE_CLASS_IMPORTS); isModified |= isModified(myCbInsertInnerClassImports, mySettings.INSERT_INNER_CLASS_IMPORTS); @@ -713,30 +691,14 @@ public class CodeStyleImportsPanel extends JPanel { return checkBox.isSelected() != value; } - private static boolean isModified(CodeStyleSettings.ImportLayoutTable list, CodeStyleSettings.ImportLayoutTable table) { + private static boolean isModified(PackageEntryTable list, PackageEntryTable table) { if(list.getEntryCount() != table.getEntryCount()) { return true; } for(int i=0; i namesToImportStaticly = new THashSet(); - String[] names = collectNamesToImport(file, namesToImportStaticly); // Note: this array may contain ".*" for unresolved imports! - Arrays.sort(names); - - ArrayList namesList = new ArrayList(); - ImportLayoutTable table = mySettings.IMPORT_LAYOUT_TABLE; - if (table != null){ - int[] entriesForName = ArrayUtil.newIntArray(names.length); - for(int i = 0; i < names.length; i++){ - entriesForName[i] = findEntryIndex(names[i]); + // Note: this array may contain ".*" for unresolved imports! + List> names = new ArrayList>(collectNamesToImport(file)); + Collections.sort(names, new Comparator>() { + public int compare(Pair o1, Pair o2) { + return o1.getFirst().compareTo(o2.getFirst()); } + }); - Entry[] entries = table.getEntries(); - for(int i = 0; i < entries.length; i++){ - Entry entry = entries[i]; - if (entry instanceof PackageEntry){ - for(int j = 0; j < names.length; j++){ - if (entriesForName[j] == i){ - namesList.add(names[j]); - names[j] = null; - } + int[] entryForName = ArrayUtil.newIntArray(names.size()); + PackageEntry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries(); + for(int i = 0; i < names.size(); i++){ + Pair pair = names.get(i); + String packageName = pair.getFirst(); + Boolean isStatic = pair.getSecond(); + entryForName[i] = findEntryIndex(packageName, isStatic, entries); + } + + List> resultList = new ArrayList>(names.size()); + for(int i = 0; i < entries.length; i++){ + PackageEntry entry = entries[i]; + //if (!entry.isSpecial()) { + for(int j = 0; j < names.size(); j++){ + if (entryForName[j] == i){ + resultList.add(names.get(j)); + names.set(j, null); } } - } + //} } - for (String name : names) { - if (name != null) namesList.add(name); + for (Pair name : names) { + if (name != null) resultList.add(name); } - names = ArrayUtil.toStringArray(namesList); TObjectIntHashMap packageToCountMap = new TObjectIntHashMap(); TObjectIntHashMap classToCountMap = new TObjectIntHashMap(); - for (String name : names) { + for (Pair pair : resultList) { + String name = pair.getFirst(); + Boolean isStatic = pair.getSecond(); String packageOrClassName = getPackageOrClassName(name); if (packageOrClassName.length() == 0) continue; - if (namesToImportStaticly.contains(name)) { + if (isStatic) { int count = classToCountMap.get(packageOrClassName); classToCountMap.put(packageOrClassName, count + 1); } @@ -123,19 +125,20 @@ public class ImportHelper{ classToCountMap.forEachEntry(new MyVisitorProcedure(false)); packageToCountMap.forEachEntry(new MyVisitorProcedure(true)); - Set classesToUseSingle = findSingleImports(file, names, classesOrPackagesToImportOnDemand, namesToImportStaticly); + Set classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand); try { - final String text = buildImportListText(names, classesOrPackagesToImportOnDemand, classesToUseSingle, namesToImportStaticly); + StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand, classesToUseSingle); String ext = StdFileTypes.JAVA.getDefaultExtension(); - final PsiJavaFile dummyFile = (PsiJavaFile)PsiFileFactory.getInstance(file.getProject()) - .createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text); + PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject()); + final PsiJavaFile dummyFile = (PsiJavaFile)factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject()); codeStyleManager.reformat(dummyFile); - PsiImportList resultList = dummyFile.getImportList(); + PsiImportList result = dummyFile.getImportList(); PsiImportList oldList = file.getImportList(); - if (oldList.isReplaceEquivalent(resultList)) return null; - return resultList; + if (oldList.isReplaceEquivalent(result)) return null; + return result; } catch(IncorrectOperationException e) { LOG.error(e); @@ -145,15 +148,17 @@ public class ImportHelper{ @NotNull private static Set findSingleImports(@NotNull final PsiJavaFile file, - @NotNull String[] names, - @NotNull final Set onDemandImports, - @NotNull Set namesToImportStaticly) { + @NotNull List> names, + @NotNull final Set onDemandImports + ) { final GlobalSearchScope resolveScope = file.getResolveScope(); Set namesToUseSingle = new THashSet(); final String thisPackageName = file.getPackageName(); final Set implicitlyImportedPackages = new THashSet(Arrays.asList(file.getImplicitlyImportedPackages())); final PsiManager manager = file.getManager(); - for (String name : names) { + for (Pair pair : names) { + String name = pair.getFirst(); + Boolean isStatic = pair.getSecond(); String prefix = getPackageOrClassName(name); if (prefix.length() == 0) continue; final boolean isImplicitlyImported = implicitlyImportedPackages.contains(prefix); @@ -174,7 +179,7 @@ public class ImportHelper{ } for (String onDemandName : onDemandImports) { if (prefix.equals(onDemandName)) continue; - if (namesToImportStaticly.contains(name)) { + if (isStatic) { PsiClass aClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(onDemandName, resolveScope); if (aClass != null) { PsiField field = aClass.findFieldByName(shortName, true); @@ -209,13 +214,14 @@ public class ImportHelper{ } @NotNull - private static String buildImportListText(@NotNull String[] names, - @NotNull final Set packagesOrClassesToImportOnDemand, - @NotNull final Set namesToUseSingle, - @NotNull Set namesToImportStaticly) { + private static StringBuilder buildImportListText(@NotNull List> names, + @NotNull final Set packagesOrClassesToImportOnDemand, + @NotNull final Set namesToUseSingle) { final Set importedPackagesOrClasses = new THashSet(); @NonNls final StringBuilder buffer = new StringBuilder(); - for (String name : names) { + for (Pair pair : names) { + String name = pair.getFirst(); + Boolean isStatic = pair.getSecond(); String packageOrClassName = getPackageOrClassName(name); final boolean implicitlyImported = JAVA_LANG_PACKAGE.equals(packageOrClassName); boolean useOnDemand = implicitlyImported || packagesOrClassesToImportOnDemand.contains(packageOrClassName); @@ -224,7 +230,7 @@ public class ImportHelper{ } if (useOnDemand && (importedPackagesOrClasses.contains(packageOrClassName) || implicitlyImported)) continue; buffer.append("import "); - if (namesToImportStaticly.contains(name)) buffer.append("static "); + if (isStatic) buffer.append("static "); if (useOnDemand) { importedPackagesOrClasses.add(packageOrClassName); buffer.append(packageOrClassName); @@ -236,7 +242,7 @@ public class ImportHelper{ buffer.append(";\n"); } - return buffer.toString(); + return buffer; } /** @@ -326,7 +332,8 @@ public class ImportHelper{ PsiImportStatement statement; if (useOnDemand) { statement = factory.createImportStatementOnDemand(packageName); - } else { + } + else { statement = factory.createImportStatement(refClass); } importList.add(statement); @@ -463,14 +470,14 @@ public class ImportHelper{ index1 = index2; index2 = t; } - Entry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries(); + PackageEntry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries(); int maxSpace = 0; for(int i = index1 + 1; i < index2; i++){ - if (entries[i] instanceof EmptyLineEntry){ + if (entries[i] == PackageEntry.BLANK_LINE_ENTRY){ int space = 0; do{ space++; - } while(entries[++i] instanceof EmptyLineEntry); + } while(entries[++i] == PackageEntry.BLANK_LINE_ENTRY); maxSpace = Math.max(maxSpace, space); } } @@ -483,34 +490,31 @@ public class ImportHelper{ mySettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND; if (classCount >= limitCount) return true; if (packageName.length() == 0) return false; - CodeStyleSettings.PackageTable table = mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND; + PackageEntryTable table = mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND; return table != null && table.contains(packageName); } - private int findEntryIndex(@NotNull String packageName){ - Entry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries(); + private static int findEntryIndex(@NotNull String packageName, boolean isStatic, @NotNull PackageEntry[] entries) { PackageEntry bestEntry = null; int bestEntryIndex = -1; + int allOtherStaticIndex = -1; + int allOtherIndex = -1; for(int i = 0; i < entries.length; i++){ - Entry entry = entries[i]; - if (entry instanceof PackageEntry){ - PackageEntry packageEntry = (PackageEntry)entry; - if (packageEntry.matchesPackageName(packageName)){ - if (bestEntry == null){ - bestEntry = packageEntry; - bestEntryIndex = i; - } - else{ - String package1 = bestEntry.getPackageName(); - String package2 = packageEntry.getPackageName(); - if (!bestEntry.isWithSubpackages()) continue; - if (!packageEntry.isWithSubpackages() || package2.length() > package1.length()) { - bestEntry = packageEntry; - bestEntryIndex = i; - } - } - } + PackageEntry entry = entries[i]; + if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) { + allOtherStaticIndex = i; } + if (entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY) { + allOtherIndex = i; + } + if (entry.isBetterMatchForPackageThan(bestEntry, packageName, isStatic)) { + bestEntry = entry; + bestEntryIndex = i; + } + } + if (bestEntryIndex == -1 && isStatic && allOtherStaticIndex == -1 && allOtherIndex != -1) { + // if no layout for static imports specified, put them among all others + bestEntryIndex = allOtherIndex; } return bestEntryIndex; } @@ -526,46 +530,45 @@ public class ImportHelper{ String className = ref.getCanonicalText(); packageName = getPackageOrClassName(className); } - return findEntryIndex(packageName); + return findEntryIndex(packageName, statement instanceof PsiImportStaticStatement, mySettings.IMPORT_LAYOUT_TABLE.getEntries()); } @NotNull - private static String[] collectNamesToImport(@NotNull PsiJavaFile file, @NotNull Set namesToImportStaticly){ - Set names = new THashSet(); + // returns list of (name, isImportStatic) pairs + private static Collection> collectNamesToImport(@NotNull PsiJavaFile file){ + Set> names = new THashSet>(); final JspFile jspFile = JspPsiUtil.getJspFile(file); - collectNamesToImport(names, file, namesToImportStaticly, jspFile); + collectNamesToImport(names, file, jspFile); if (jspFile != null) { PsiFile[] files = ArrayUtil.mergeArrays(JspSpiUtil.getIncludingFiles(jspFile), JspSpiUtil.getIncludedFiles(jspFile), PsiFile.class); for (PsiFile includingFile : files) { final PsiFile javaRoot = includingFile.getViewProvider().getPsi(StdLanguages.JAVA); if (javaRoot instanceof PsiJavaFile && file != javaRoot) { - collectNamesToImport(names, (PsiJavaFile)javaRoot, namesToImportStaticly, jspFile); + collectNamesToImport(names, (PsiJavaFile)javaRoot, jspFile); } } } - addUnresolvedImportNames(names, file, namesToImportStaticly); + addUnresolvedImportNames(names, file); - return ArrayUtil.toStringArray(names); + return names; } - private static void collectNamesToImport(@NotNull final Set names, + private static void collectNamesToImport(@NotNull final Set> names, @NotNull final PsiJavaFile file, - @NotNull final Set namesToImportStaticly, PsiFile context) { String packageName = file.getPackageName(); final PsiElement[] roots = file.getPsiRoots(); for (PsiElement root : roots) { - addNamesToImport(names, root, packageName, namesToImportStaticly, context); + addNamesToImport(names, root, packageName, context); } } - private static void addNamesToImport(@NotNull Set names, + private static void addNamesToImport(@NotNull Set> names, @NotNull PsiElement scope, @NotNull String thisPackageName, - @NotNull Set namesToImportStaticly, PsiFile context){ if (scope instanceof PsiImportList) return; @@ -579,9 +582,7 @@ public class ImportHelper{ for(final PsiReference reference : child.getReferences()){ if (!(reference instanceof PsiJavaReference)) continue; final PsiJavaReference javaReference = (PsiJavaReference)reference; - if (javaReference instanceof JavaClassReference){ - if(((JavaClassReference)javaReference).getContextReference() != null) continue; - } + if (javaReference instanceof JavaClassReference && ((JavaClassReference)javaReference).getContextReference() != null) continue; PsiJavaCodeReferenceElement referenceElement = null; if (reference instanceof PsiJavaCodeReferenceElement) { referenceElement = (PsiJavaCodeReferenceElement)child; @@ -599,6 +600,7 @@ public class ImportHelper{ if (refElement == null && referenceElement != null) { refElement = ResolveClassUtil.resolveClass(referenceElement); // might be uncomplete code } + if (refElement == null) continue; PsiElement currentFileResolveScope = resolveResult.getCurrentFileResolveScope(); if (!(currentFileResolveScope instanceof PsiImportStatementBase)) continue; @@ -606,35 +608,29 @@ public class ImportHelper{ continue; } - if (refElement != null) { - //Add names imported statically - if (referenceElement != null) { - if (currentFileResolveScope instanceof PsiImportStaticStatement) { - PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)currentFileResolveScope; - String name = importStaticStatement.getImportReference().getCanonicalText(); - if (importStaticStatement.isOnDemand()) { - String refName = referenceElement.getReferenceName(); - if (refName != null) name = name + "." + refName; - } - names.add(name); - namesToImportStaticly.add(name); - continue; + if (referenceElement != null) { + if (currentFileResolveScope instanceof PsiImportStaticStatement) { + PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)currentFileResolveScope; + String name = importStaticStatement.getImportReference().getCanonicalText(); + if (importStaticStatement.isOnDemand()) { + String refName = referenceElement.getReferenceName(); + if (refName != null) name = name + "." + refName; } + names.add(Pair.create(name, Boolean.TRUE)); + continue; } + } - if (refElement instanceof PsiClass) { - String qName = ((PsiClass)refElement).getQualifiedName(); - if (hasPackage(qName, thisPackageName)) continue; - names.add(qName); - } + if (refElement instanceof PsiClass) { + String qName = ((PsiClass)refElement).getQualifiedName(); + if (hasPackage(qName, thisPackageName)) continue; + names.add(Pair.create(qName, Boolean.FALSE)); } } } } - private static void addUnresolvedImportNames(@NotNull Set set, - @NotNull PsiJavaFile file, - @NotNull Set namesToImportStaticly) { + private static void addUnresolvedImportNames(@NotNull Set> names, @NotNull PsiJavaFile file) { PsiImportStatementBase[] imports = file.getImportList().getAllImportStatements(); for (PsiImportStatementBase anImport : imports) { PsiJavaCodeReferenceElement ref = anImport.getImportReference(); @@ -645,10 +641,7 @@ public class ImportHelper{ if (anImport.isOnDemand()) { text += ".*"; } - if (anImport instanceof PsiImportStaticStatement) { - namesToImportStaticly.add(text); - } - set.add(text); + names.add(Pair.create(text, anImport instanceof PsiImportStaticStatement)); } } } diff --git a/platform/lang-api/src/com/intellij/application/options/IndentOptionsEditor.java b/platform/lang-api/src/com/intellij/application/options/IndentOptionsEditor.java index 9f1fa01de6e6..040ad4d4f166 100644 --- a/platform/lang-api/src/com/intellij/application/options/IndentOptionsEditor.java +++ b/platform/lang-api/src/com/intellij/application/options/IndentOptionsEditor.java @@ -16,9 +16,10 @@ package com.intellij.application.options; -import com.intellij.ui.OptionGroup; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.ui.OptionGroup; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -108,7 +109,7 @@ public class IndentOptionsEditor extends OptionGroup { options.USE_TAB_CHARACTER = myCbUseTab.isSelected(); } - public void reset(final CodeStyleSettings settings, CodeStyleSettings.IndentOptions options) { + public void reset(@NotNull CodeStyleSettings settings, @NotNull CodeStyleSettings.IndentOptions options) { myTabSizeField.setText(String.valueOf(options.TAB_SIZE)); myCbUseTab.setSelected(options.USE_TAB_CHARACTER); diff --git a/platform/lang-api/src/com/intellij/application/options/SmartIndentOptionsEditor.java b/platform/lang-api/src/com/intellij/application/options/SmartIndentOptionsEditor.java index a63b7ebd984e..927cb3d514c0 100644 --- a/platform/lang-api/src/com/intellij/application/options/SmartIndentOptionsEditor.java +++ b/platform/lang-api/src/com/intellij/application/options/SmartIndentOptionsEditor.java @@ -18,6 +18,7 @@ package com.intellij.application.options; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.psi.codeStyle.CodeStyleSettings; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -63,7 +64,7 @@ public class SmartIndentOptionsEditor extends IndentOptionsEditor { options.SMART_TABS = isSmartTabValid(options.INDENT_SIZE, options.TAB_SIZE) && myCbSmartTabs.isSelected(); } - public void reset(final CodeStyleSettings settings, final CodeStyleSettings.IndentOptions options) { + public void reset(@NotNull final CodeStyleSettings settings, @NotNull final CodeStyleSettings.IndentOptions options) { super.reset(settings, options); myContinuationIndentField.setText(String.valueOf(options.CONTINUATION_INDENT_SIZE)); myCbSmartTabs.setSelected(options.SMART_TABS); diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index 44c379554152..cffb51019d20 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -35,7 +35,7 @@ import java.lang.reflect.Modifier; import java.util.*; public class CodeStyleSettings implements Cloneable, JDOMExternalizable { - private ClassMap myCustomSettings = new ClassMap(); + private final ClassMap myCustomSettings = new ClassMap(); @NonNls private static final String ADDITIONAL_INDENT_OPTIONS = "ADDITIONAL_INDENT_OPTIONS"; @NonNls private static final String FILETYPE = "fileType"; @@ -56,12 +56,12 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { } private void initImports() { - PACKAGES_TO_USE_IMPORT_ON_DEMAND.insertEntryAt(new PackageTable.Entry("java.awt", false), 0); - PACKAGES_TO_USE_IMPORT_ON_DEMAND.insertEntryAt(new PackageTable.Entry("javax.swing", false), 1); - IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.PackageEntry("", true), 0); - IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.EmptyLineEntry(), 1); - IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.PackageEntry("javax", true), 2); - IMPORT_LAYOUT_TABLE.insertEntryAt(new ImportLayoutTable.PackageEntry("java", true), 3); + PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false, "java.awt", false)); + PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false,"javax.swing", false)); + IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY); + IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY); + IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "javax", true)); + IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "java", true)); } private void initTypeToName() { @@ -102,67 +102,64 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { } public CodeStyleSettings clone() { - try { - CodeStyleSettings clone = (CodeStyleSettings)super.clone(); - - copyCustomSettings(this, clone); - return clone; - } - catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } + CodeStyleSettings clone = new CodeStyleSettings(); + clone.copyFrom(this); + return clone; } - private static void copyCustomSettings(CodeStyleSettings from, final CodeStyleSettings to) throws CloneNotSupportedException { - to.myCustomSettings = new ClassMap(); + private void copyCustomSettingsFrom(CodeStyleSettings from) { + assert from != this; + myCustomSettings.clear(); for (final CustomCodeStyleSettings settings : from.myCustomSettings.values()) { - to.addCustomSettings((CustomCodeStyleSettings) settings.clone()); + addCustomSettings((CustomCodeStyleSettings) settings.clone()); } - to.FIELD_TYPE_TO_NAME = (TypeToNameMap)from.FIELD_TYPE_TO_NAME.clone(); - to.STATIC_FIELD_TYPE_TO_NAME = (TypeToNameMap)from.STATIC_FIELD_TYPE_TO_NAME.clone(); - to.PARAMETER_TYPE_TO_NAME = (TypeToNameMap)from.PARAMETER_TYPE_TO_NAME.clone(); - to.LOCAL_VARIABLE_TYPE_TO_NAME = (TypeToNameMap)from.LOCAL_VARIABLE_TYPE_TO_NAME.clone(); + FIELD_TYPE_TO_NAME.copyFrom(from.FIELD_TYPE_TO_NAME); + STATIC_FIELD_TYPE_TO_NAME.copyFrom(from.STATIC_FIELD_TYPE_TO_NAME); + PARAMETER_TYPE_TO_NAME.copyFrom(from.PARAMETER_TYPE_TO_NAME); + LOCAL_VARIABLE_TYPE_TO_NAME.copyFrom(from.LOCAL_VARIABLE_TYPE_TO_NAME); - to.PACKAGES_TO_USE_IMPORT_ON_DEMAND = (PackageTable)from.PACKAGES_TO_USE_IMPORT_ON_DEMAND.clone(); - to.IMPORT_LAYOUT_TABLE = (ImportLayoutTable)from.IMPORT_LAYOUT_TABLE.clone(); + PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(from.PACKAGES_TO_USE_IMPORT_ON_DEMAND); + IMPORT_LAYOUT_TABLE.copyFrom(from.IMPORT_LAYOUT_TABLE); - to.OTHER_INDENT_OPTIONS = (IndentOptions)from.OTHER_INDENT_OPTIONS.clone(); + OTHER_INDENT_OPTIONS.copyFrom(from.OTHER_INDENT_OPTIONS); - to.myAdditionalIndentOptions = new LinkedHashMap(); + myAdditionalIndentOptions.clear(); for(Map.Entry optionEntry: from.myAdditionalIndentOptions.entrySet()) { - to.myAdditionalIndentOptions.put(optionEntry.getKey(),(IndentOptions)optionEntry.getValue().clone()); + IndentOptions options = optionEntry.getValue(); + myAdditionalIndentOptions.put(optionEntry.getKey(),(IndentOptions)options.clone()); } } - public void copyFrom(CodeStyleSettings settings) { - Field[] fields = getClass().getDeclaredFields(); + public void copyFrom(CodeStyleSettings from) { + copyPublicFields(from, this); + + this.copyCustomSettingsFrom(from); + } + + private static void copyPublicFields(Object from, Object to) { + assert from != to; + Field[] fields = to.getClass().getDeclaredFields(); for (Field field : fields) { if (isPublic(field) && !isFinal(field)) { try { - copyFieldValue(settings, field); + copyFieldValue(from, to, field); } catch (Exception e) { throw new RuntimeException(e); } } } - - try { - copyCustomSettings(settings, this); - } - catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } } - private void copyFieldValue(final CodeStyleSettings settings, final Field field) - throws IllegalAccessException, CloneNotSupportedException { + + private static void copyFieldValue(final Object from, Object to, final Field field) + throws IllegalAccessException { Class fieldType = field.getType(); if (fieldType.isPrimitive()) { - field.set(this, field.get(settings)); + field.set(to, field.get(from)); } else if (fieldType.equals(String.class)) { - field.set(this, field.get(settings)); + field.set(to, field.get(from)); } else { System.out.println("Field not copied " + field.getName()); @@ -248,18 +245,22 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { result = 31 * result + (LABEL_INDENT_ABSOLUTE ? 1 : 0); return result; } + + public void copyFrom(IndentOptions other) { + copyPublicFields(other, this); + } } @Deprecated - public IndentOptions JAVA_INDENT_OPTIONS = new IndentOptions(); + public final IndentOptions JAVA_INDENT_OPTIONS = new IndentOptions(); @Deprecated - public IndentOptions JSP_INDENT_OPTIONS = new IndentOptions(); + public final IndentOptions JSP_INDENT_OPTIONS = new IndentOptions(); @Deprecated - public IndentOptions XML_INDENT_OPTIONS = new IndentOptions(); + public final IndentOptions XML_INDENT_OPTIONS = new IndentOptions(); - public IndentOptions OTHER_INDENT_OPTIONS = new IndentOptions(); + public final IndentOptions OTHER_INDENT_OPTIONS = new IndentOptions(); - private Map myAdditionalIndentOptions = new LinkedHashMap(); + private final Map myAdditionalIndentOptions = new LinkedHashMap(); private static final String ourSystemLineSeparator = SystemProperties.getLineSeparator(); @@ -720,10 +721,10 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { public boolean PREFER_LONGER_NAMES = true; - public TypeToNameMap FIELD_TYPE_TO_NAME = new TypeToNameMap(); - public TypeToNameMap STATIC_FIELD_TYPE_TO_NAME = new TypeToNameMap(); - @NonNls public TypeToNameMap PARAMETER_TYPE_TO_NAME = new TypeToNameMap(); - public TypeToNameMap LOCAL_VARIABLE_TYPE_TO_NAME = new TypeToNameMap(); + public final TypeToNameMap FIELD_TYPE_TO_NAME = new TypeToNameMap(); + public final TypeToNameMap STATIC_FIELD_TYPE_TO_NAME = new TypeToNameMap(); + @NonNls public final TypeToNameMap PARAMETER_TYPE_TO_NAME = new TypeToNameMap(); + public final TypeToNameMap LOCAL_VARIABLE_TYPE_TO_NAME = new TypeToNameMap(); //----------------- 'final' modifier settings ------- public boolean GENERATE_FINAL_LOCALS = false; @@ -735,14 +736,15 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { //----------------- IMPORTS -------------------- + public boolean LAYOUT_STATIC_IMPORTS_SEPARATELY = true; public boolean USE_FQ_CLASS_NAMES = false; public boolean USE_FQ_CLASS_NAMES_IN_JAVADOC = true; public boolean USE_SINGLE_CLASS_IMPORTS = true; public boolean INSERT_INNER_CLASS_IMPORTS = false; public int CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 5; public int NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = 3; - public PackageTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageTable(); - public ImportLayoutTable IMPORT_LAYOUT_TABLE = new ImportLayoutTable(); + public final PackageEntryTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageEntryTable(); + public final PackageEntryTable IMPORT_LAYOUT_TABLE = new PackageEntryTable(); public boolean OPTIMIZE_IMPORTS_ON_THE_FLY = false; public boolean ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY = false; @@ -1115,6 +1117,19 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { public void readExternal(Element element) throws InvalidDataException { DefaultJDOMExternalizer.readExternal(this, element); + if (LAYOUT_STATIC_IMPORTS_SEPARATELY) { + // add entry if there is none + boolean found = false; + for (PackageEntry entry : IMPORT_LAYOUT_TABLE.getEntries()) { + if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) { + found = true; + break; + } + } + if (!found) { + IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY); + } + } importOldIndentOptions(element); for (final CustomCodeStyleSettings settings : myCustomSettings.values()) { settings.readExternal(element); @@ -1269,9 +1284,9 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { return getIndentOptions(fileType).USE_TAB_CHARACTER; } - public static class TypeToNameMap implements JDOMExternalizable, Cloneable { - private ArrayList myPatterns = new ArrayList(); - private ArrayList myNames = new ArrayList(); + public static class TypeToNameMap implements JDOMExternalizable { + private final List myPatterns = new ArrayList(); + private final List myNames = new ArrayList(); public void addPair(String pattern, String name) { myPatterns.add(pattern); @@ -1323,11 +1338,12 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { } } - public Object clone() throws CloneNotSupportedException { - TypeToNameMap clon = (TypeToNameMap)TypeToNameMap.super.clone(); - clon.myPatterns = (ArrayList)myPatterns.clone(); - clon.myNames = (ArrayList)myNames.clone(); - return clon; + public void copyFrom(TypeToNameMap from) { + assert from != this; + myPatterns.clear(); + myPatterns.addAll(from.myPatterns); + myNames.clear(); + myNames.addAll(from.myNames); } public boolean equals(Object other) { @@ -1371,311 +1387,6 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { } - public static class PackageTable implements JDOMExternalizable, Cloneable { - public static class Entry implements Cloneable { - final String packageName; - final boolean withSubpackages; - - public Entry(@NonNls String packageName, boolean withSubpackages) { - this.packageName = packageName; - this.withSubpackages = withSubpackages; - } - - public String getPackageName() { - return packageName; - } - - public boolean isWithSubpackages() { - return withSubpackages; - } - - public boolean equals(Object obj) { - if (!(obj instanceof Entry)) { - return false; - } - Entry entry = (Entry)obj; - return entry.withSubpackages == withSubpackages - && Comparing.equal(entry.packageName, packageName); - } - - public int hashCode() { - if (packageName == null) { - return 0; - } - return packageName.hashCode(); - } - - } - - private ArrayList myEntries = new ArrayList(); - - public boolean equals(Object obj) { - if (!(obj instanceof PackageTable)) { - return false; - } - PackageTable other = (PackageTable)obj; - if (other.myEntries.size() != myEntries.size()) { - return false; - } - for (int i = 0; i < myEntries.size(); i++) { - Entry entry = myEntries.get(i); - Entry otherentry = other.myEntries.get(i); - if (!Comparing.equal(entry, otherentry)) { - return false; - } - } - return true; - } - - public int hashCode() { - if (!myEntries.isEmpty() && myEntries.get(0) != null) { - return myEntries.get(0).hashCode(); - } - return 0; - } - - public Object clone() throws CloneNotSupportedException { - PackageTable clon = (PackageTable)PackageTable.super.clone(); - clon.myEntries = (ArrayList)myEntries.clone(); - return clon; - } - - public void copyFrom(PackageTable packageTable) { - myEntries = (ArrayList)packageTable.myEntries.clone(); - } - - public Entry[] getEntries() { - return myEntries.toArray(new Entry[myEntries.size()]); - } - - public void insertEntryAt(Entry entry, int i) { - myEntries.add(i, entry); - } - - public void removeEntryAt(int i) { - myEntries.remove(i); - } - - public Entry getEntryAt(int i) { - return myEntries.get(i); - } - - public int getEntryCount() { - return myEntries.size(); - } - - public void setEntryAt(Entry entry, int i) { - myEntries.set(i, entry); - } - - public boolean contains(String packageName) { - for (Entry entry : myEntries) { - if (packageName.startsWith(entry.packageName)) { - if (packageName.length() == entry.packageName.length()) return true; - if (entry.withSubpackages) { - if (packageName.charAt(entry.packageName.length()) == '.') return true; - } - } - } - return false; - } - - public void readExternal(@NonNls Element element) throws InvalidDataException { - myEntries.clear(); - - for (final Object o : element.getChildren("package")) { - @NonNls Element e = (Element)o; - String packageName = e.getAttributeValue("name"); - boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages")); - if (packageName == null) { - throw new InvalidDataException(); - } - myEntries.add(new Entry(packageName, withSubpackages)); - } - } - - public void writeExternal(Element parentNode) throws WriteExternalException { - for (Entry entry : myEntries) { - @NonNls Element element = new Element("package"); - parentNode.addContent(element); - element.setAttribute("name", entry.packageName); - element.setAttribute("withSubpackages", Boolean.toString(entry.withSubpackages)); - } - } - } - - public static class ImportLayoutTable implements JDOMExternalizable, Cloneable { - private ArrayList myEntries = new ArrayList(); - - public interface Entry { - } - - public static class PackageEntry implements Entry { - private final String myPackageName; - private final boolean myWithSubpackages; - - public PackageEntry(@NonNls String packageName, boolean withSubpackages) { - myPackageName = packageName; - myWithSubpackages = withSubpackages; - } - - public String getPackageName() { - return myPackageName; - } - - public boolean isWithSubpackages() { - return myWithSubpackages; - } - - public boolean matchesPackageName(String packageName) { - if (myPackageName.length() == 0 && myWithSubpackages) return true; - if (packageName.startsWith(myPackageName)) { - if (packageName.length() == myPackageName.length()) return true; - if (myWithSubpackages) { - if (packageName.charAt(myPackageName.length()) == '.') return true; - } - } - return false; - } - - public boolean matchesClassName(String className) { - int dotIndex = className.lastIndexOf('.'); - String packageName = dotIndex < 0 ? "" : className.substring(0, dotIndex); - return matchesPackageName(packageName); - } - - public boolean equals(Object obj) { - if (!(obj instanceof PackageEntry)) { - return false; - } - PackageEntry entry = (PackageEntry)obj; - return entry.myWithSubpackages == myWithSubpackages - && Comparing.equal(entry.myPackageName, myPackageName); - } - - public int hashCode() { - if (myPackageName == null) { - return 0; - } - return myPackageName.hashCode(); - } - } - - public static class EmptyLineEntry implements Entry { - public boolean equals(Object obj) { - return obj instanceof EmptyLineEntry; - } - - public int hashCode() { - return 100; - } - } - - - public void copyFrom(ImportLayoutTable importLayoutTable) { - myEntries = (ArrayList)importLayoutTable.myEntries.clone(); - } - - public Entry[] getEntries() { - return myEntries.toArray(new Entry[myEntries.size()]); - } - - public void insertEntryAt(Entry entry, int i) { - myEntries.add(i, entry); - } - - public void removeEntryAt(int i) { - myEntries.remove(i); - } - - public Entry getEntryAt(int i) { - return myEntries.get(i); - } - - public int getEntryCount() { - return myEntries.size(); - } - - public void setEntryAt(Entry entry, int i) { - myEntries.set(i, entry); - } - - public void readExternal(Element element) throws InvalidDataException { - myEntries.clear(); - List children = element.getChildren(); - for (final Object aChildren : children) { - @NonNls Element e = (Element)aChildren; - @NonNls String name = e.getName(); - if ("package".equals(name)) { - String packageName = e.getAttributeValue("name"); - boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages")); - if (packageName == null) { - throw new InvalidDataException(); - } - myEntries.add(new PackageEntry(packageName, withSubpackages)); - } - else { - if ("emptyLine".equals(name)) { - myEntries.add(new EmptyLineEntry()); - } - } - - } - - } - - public void writeExternal(Element parentNode) throws WriteExternalException { - for (Entry myEntry : myEntries) { - if (myEntry instanceof PackageEntry) { - PackageEntry entry = (PackageEntry)myEntry; - @NonNls Element element = new Element("package"); - parentNode.addContent(element); - element.setAttribute("name", entry.getPackageName()); - element.setAttribute("withSubpackages", entry.isWithSubpackages() ? "true" : "false"); - } - else { - if (myEntry instanceof EmptyLineEntry) { - @NonNls Element element = new Element("emptyLine"); - parentNode.addContent(element); - } - } - } - } - - public boolean equals(Object obj) { - if (!(obj instanceof ImportLayoutTable)) { - return false; - } - ImportLayoutTable other = (ImportLayoutTable)obj; - if (other.myEntries.size() != myEntries.size()) { - return false; - } - for (int i = 0; i < myEntries.size(); i++) { - Entry entry = myEntries.get(i); - Entry otherentry = other.myEntries.get(i); - if (!Comparing.equal(entry, otherentry)) { - return false; - } - } - return true; - } - - public int hashCode() { - if (!myEntries.isEmpty() && myEntries.get(0) != null) { - return myEntries.get(0).hashCode(); - } - return 0; - } - - public Object clone() throws CloneNotSupportedException { - ImportLayoutTable clon = (ImportLayoutTable)ImportLayoutTable.super.clone(); - clon.myEntries = (ArrayList)myEntries.clone(); - return clon; - } - - - } - private void registerAdditionalIndentOptions(FileType fileType, IndentOptions options) { myAdditionalIndentOptions.put(fileType, options); } @@ -1689,9 +1400,8 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { private void loadAdditionalIndentOptions() { myLoadedAdditionalIndentOptions = true; - final FileTypeIndentOptionsProvider[] fileTypeIndentOptionsProviders = - Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME); - for (final FileTypeIndentOptionsProvider provider : fileTypeIndentOptionsProviders) { + final FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME); + for (final FileTypeIndentOptionsProvider provider : providers) { if (!myAdditionalIndentOptions.containsKey(provider.getFileType())) { registerAdditionalIndentOptions(provider.getFileType(), provider.createIndentOptions()); } @@ -1710,7 +1420,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { } private static class TempFileType implements FileType { - private String myExtension; + private final String myExtension; private TempFileType(@NotNull final String extension) { myExtension = extension; diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java b/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java new file mode 100755 index 000000000000..5eaf66cc7c96 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntry.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle; + +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: cdr + */ +public class PackageEntry { + private final String myPackageName; + private final boolean myWithSubpackages; + private final boolean isStatic; + + public PackageEntry(boolean isStatic, @NotNull @NonNls String packageName, boolean withSubpackages) { + this.isStatic = isStatic; + myPackageName = packageName; + myWithSubpackages = withSubpackages; + } + + public String getPackageName() { + return myPackageName; + } + + public boolean isWithSubpackages() { + return myWithSubpackages; + } + + public boolean isStatic() { + return isStatic; + } + + public boolean matchesPackageName(String packageName) { + if (packageName.startsWith(myPackageName)) { + if (packageName.length() == myPackageName.length()) return true; + if (myWithSubpackages) { + if (packageName.charAt(myPackageName.length()) == '.') return true; + } + } + return false; + } + + public boolean equals(Object obj) { + if (!(obj instanceof PackageEntry)) { + return false; + } + PackageEntry entry = (PackageEntry)obj; + return entry.myWithSubpackages == myWithSubpackages + && entry.isStatic() == isStatic() + && Comparing.equal(entry.myPackageName, myPackageName); + } + + public int hashCode() { + return myPackageName.hashCode(); + } + + public static final PackageEntry BLANK_LINE_ENTRY = new PackageEntry(false, "", true){ + @Override + public boolean matchesPackageName(String packageName) { + return false; + } + }; + public static final PackageEntry ALL_OTHER_IMPORTS_ENTRY = new PackageEntry(false, "", true){ + @Override + public boolean matchesPackageName(String packageName) { + return true; + } + }; + public static final PackageEntry ALL_OTHER_STATIC_IMPORTS_ENTRY = new PackageEntry(true, "", true){ + @Override + public boolean matchesPackageName(String packageName) { + return true; + } + }; + + public boolean isSpecial() { + return this == BLANK_LINE_ENTRY || this == ALL_OTHER_IMPORTS_ENTRY || this == ALL_OTHER_STATIC_IMPORTS_ENTRY; + } + + public boolean isBetterMatchForPackageThan(@Nullable PackageEntry entry, @NotNull String packageName, boolean isStatic) { + if (isStatic() != isStatic || !matchesPackageName(packageName)) return false; + if (entry == null) { + return true; + } + if (entry.isStatic() != isStatic) return false; + if (entry.isWithSubpackages() != isWithSubpackages()) { + return !isWithSubpackages(); + } + + return StringUtil.countChars(entry.getPackageName(), '.') < StringUtil.countChars(getPackageName(), '.'); + } + + @Override + public String toString() { + return (isStatic() ? "static " : "") + getPackageName(); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java b/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java new file mode 100755 index 000000000000..15acfa85b27f --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/PackageEntryTable.java @@ -0,0 +1,166 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.codeStyle; + +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; + +import java.util.ArrayList; +import java.util.List; + +/** +* User: cdr +*/ +public class PackageEntryTable implements JDOMExternalizable, Cloneable { + private final List myEntries = new ArrayList(); + + public boolean equals(Object obj) { + if (!(obj instanceof PackageEntryTable)) { + return false; + } + PackageEntryTable other = (PackageEntryTable)obj; + if (other.myEntries.size() != myEntries.size()) { + return false; + } + for (int i = 0; i < myEntries.size(); i++) { + PackageEntry entry = myEntries.get(i); + PackageEntry otherentry = other.myEntries.get(i); + if (!Comparing.equal(entry, otherentry)) { + return false; + } + } + return true; + } + + public int hashCode() { + if (!myEntries.isEmpty() && myEntries.get(0) != null) { + return myEntries.get(0).hashCode(); + } + return 0; + } + + public Object clone() throws CloneNotSupportedException { + PackageEntryTable clon = new PackageEntryTable(); + clon.copyFrom(this); + return clon; + } + + public void copyFrom(PackageEntryTable packageTable) { + myEntries.clear(); + myEntries.addAll(packageTable.myEntries); + } + + public PackageEntry[] getEntries() { + return myEntries.toArray(new PackageEntry[myEntries.size()]); + } + + public void insertEntryAt(PackageEntry entry, int i) { + myEntries.add(i, entry); + } + + public void removeEntryAt(int i) { + myEntries.remove(i); + } + + public PackageEntry getEntryAt(int i) { + return myEntries.get(i); + } + + public int getEntryCount() { + return myEntries.size(); + } + + public void setEntryAt(PackageEntry entry, int i) { + myEntries.set(i, entry); + } + + public boolean contains(String packageName) { + for (PackageEntry entry : myEntries) { + if (packageName.startsWith(entry.getPackageName())) { + if (packageName.length() == entry.getPackageName().length()) return true; + if (entry.isWithSubpackages()) { + if (packageName.charAt(entry.getPackageName().length()) == '.') return true; + } + } + } + return false; + } + + public void readExternal(Element element) throws InvalidDataException { + myEntries.clear(); + List children = element.getChildren(); + for (final Object aChildren : children) { + @NonNls Element e = (Element)aChildren; + @NonNls String name = e.getName(); + if ("package".equals(name)) { + String packageName = e.getAttributeValue("name"); + boolean isStatic = Boolean.parseBoolean(e.getAttributeValue("static")); + boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages")); + if (packageName == null) { + throw new InvalidDataException(); + } + PackageEntry entry; + if (packageName.length() == 0) { + entry = isStatic ? PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY : PackageEntry.ALL_OTHER_IMPORTS_ENTRY; + } + else { + entry = new PackageEntry(isStatic, packageName, withSubpackages); + } + myEntries.add(entry); + } + else { + if ("emptyLine".equals(name)) { + myEntries.add(PackageEntry.BLANK_LINE_ENTRY); + } + } + } + } + + public void writeExternal(Element parentNode) throws WriteExternalException { + for (PackageEntry entry : myEntries) { + if (entry == PackageEntry.BLANK_LINE_ENTRY) { + @NonNls Element element = new Element("emptyLine"); + parentNode.addContent(element); + } + else { + @NonNls Element element = new Element("package"); + parentNode.addContent(element); + String packageName = entry.getPackageName(); + element.setAttribute("name", entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY ? "": packageName); + element.setAttribute("withSubpackages", entry.isWithSubpackages() ? "true" : "false"); + element.setAttribute("static", entry.isStatic() ? "true" : "false"); + } + } + } + + public void removeEmptyPackages() { + for(int i = myEntries.size()-1; i>=0; i--){ + PackageEntry entry = myEntries.get(i); + if(StringUtil.isEmptyOrSpaces(entry.getPackageName())) { + removeEntryAt(i); + } + } + } + + public void addEntry(PackageEntry entry) { + myEntries.add(entry); + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java index a9fdb375e5bc..5e2d1a522b1e 100644 --- a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java @@ -16,7 +16,6 @@ package com.intellij.application.options; -import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.highlighter.EditorHighlighter; @@ -129,13 +128,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { for(Map.Entry entry: myAdditionalIndentOptions.entrySet()) { FileType ft = entry.getKey(); - String tabName; - if (ft instanceof LanguageFileType) { - tabName = ((LanguageFileType) ft).getLanguage().getDisplayName(); - } - else { - tabName = ft.getName(); - } + String tabName = ft instanceof LanguageFileType ? ((LanguageFileType)ft).getLanguage().getDisplayName() : ft.getName(); myIndentOptionsTabs.addTab(tabName, entry.getValue().createPanel()); } @@ -195,7 +188,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { @Nullable private static FileTypeIndentOptionsProvider getDefaultIndentProvider() { FileTypeIndentOptionsProvider[] providers = Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME); - return (providers.length == 0) ? null : providers[0]; + return providers.length == 0 ? null : providers[0]; } public void apply(CodeStyleSettings settings) { @@ -208,8 +201,10 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { else { myOtherIndentOptions.apply(settings, settings.OTHER_INDENT_OPTIONS); - for(FileType fileType: myAdditionalIndentOptions.keySet()) { - myAdditionalIndentOptions.get(fileType).apply(settings, settings.getAdditionalIndentOptions(fileType)); + for(Map.Entry entry : myAdditionalIndentOptions.entrySet()) { + FileType fileType = entry.getKey(); + IndentOptionsEditor editor = entry.getValue(); + editor.apply(settings, settings.getAdditionalIndentOptions(fileType)); } } @@ -221,14 +216,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { } private IndentOptionsEditor findEditorForSameIndents() { - IndentOptionsEditor theEditor; - if (myAdditionalIndentOptions.isEmpty()) { - theEditor = myOtherIndentOptions; - } - else { - theEditor = myAdditionalIndentOptions.values().iterator().next(); - } - return theEditor; + return myAdditionalIndentOptions.isEmpty() ? myOtherIndentOptions : myAdditionalIndentOptions.values().iterator().next(); } private int getRightMarginImpl() { @@ -275,18 +263,16 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { return true; } - for(FileType fileType: myAdditionalIndentOptions.keySet()) { - if (myAdditionalIndentOptions.get(fileType).isModified(settings, settings.getAdditionalIndentOptions(fileType))) { + for(Map.Entry entry : myAdditionalIndentOptions.entrySet()) { + IndentOptionsEditor editor = entry.getValue(); + FileType fileType = entry.getKey(); + if (editor.isModified(settings, settings.getAdditionalIndentOptions(fileType))) { return true; } } } - if (!myRightMarginField.getText().equals(String.valueOf(settings.RIGHT_MARGIN))) { - return true; - } - - return false; + return !myRightMarginField.getText().equals(String.valueOf(settings.RIGHT_MARGIN)); } public JComponent getPanel() { @@ -299,14 +285,15 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel { myOtherIndentOptions.reset(settings, settings.OTHER_INDENT_OPTIONS); boolean first = true; - for(FileType fileType: myAdditionalIndentOptions.keySet()) { - final IndentOptionsEditor editor = myAdditionalIndentOptions.get(fileType); + for(Map.Entry entry : myAdditionalIndentOptions.entrySet()) { + final IndentOptionsEditor editor = entry.getValue(); if (settings.USE_SAME_INDENTS && first) { first = false; editor.reset(settings, settings.OTHER_INDENT_OPTIONS); } else { - editor.reset(settings, settings.getAdditionalIndentOptions(fileType)); + FileType type = entry.getKey(); + editor.reset(settings, settings.getAdditionalIndentOptions(type)); } } diff --git a/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java b/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java index 2faf9e618f76..720e4c1e2c04 100644 --- a/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java @@ -53,8 +53,9 @@ public class BooleanTableCellRenderer extends JCheckBox implements TableCellRend setBackground(table.getBackground()); } if (value instanceof String) { - setSelected((Boolean.parseBoolean((String)value))); - } else { + setSelected(Boolean.parseBoolean((String)value)); + } + else { setSelected(((Boolean)value).booleanValue()); } return this; diff --git a/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java b/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java index aac51c89cbda..68036bba9ca4 100644 --- a/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java +++ b/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java @@ -165,8 +165,20 @@ public class DefaultJDOMExternalizer { Field field = data.getClass().getField(fieldName); Class type = field.getType(); int modifiers = field.getModifiers(); - if ((modifiers & Modifier.PUBLIC) == 0 || (modifiers & Modifier.STATIC) != 0 || (modifiers & Modifier.FINAL) != 0) continue; + if ((modifiers & Modifier.PUBLIC) == 0 || (modifiers & Modifier.STATIC) != 0) continue; field.setAccessible(true); // class might be non-public + if ((modifiers & Modifier.FINAL) != 0) { + // read external contents of final field + Object value = field.get(data); + if (ReflectionCache.isInstance(value, JDOMExternalizable.class)) { + final List children = e.getChildren("value"); + for (Object child : children) { + Element valueTag = (Element)child; + ((JDOMExternalizable)value).readExternal(valueTag); + } + } + continue; + } String value = e.getAttributeValue("value"); if (type.isPrimitive()) { if (value != null) { diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index bec0ccd24cb4..0be45c4b43cf 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1274,17 +1274,20 @@ public class StringUtil { return result; } - public static int countNewLines(final CharSequence text) { - int lineShift = 0; + public static int countNewLines(@NotNull CharSequence text) { + return countChars(text, '\n'); + } + + public static int countChars(@NotNull CharSequence text, char c) { + int count = 0; for(int i = 0; i < text.length(); ++i) { final char ch = text.charAt(i); - - if (ch == '\n') { - ++lineShift; + if (ch == c) { + ++count; } } - return lineShift; + return count; } public static String capitalsOnly(String s) { diff --git a/platform/util/src/com/intellij/util/containers/ClassMap.java b/platform/util/src/com/intellij/util/containers/ClassMap.java index 66d1741db905..de530228768d 100644 --- a/platform/util/src/com/intellij/util/containers/ClassMap.java +++ b/platform/util/src/com/intellij/util/containers/ClassMap.java @@ -31,7 +31,7 @@ public class ClassMap { this(new THashMap()); } protected ClassMap(Map map) { - myMap = map; + myMap = map; } public void put(Class aClass, T value) { @@ -67,4 +67,8 @@ public class ClassMap { public final Collection values() { return myMap.values(); } + + public void clear() { + myMap.clear(); + } }