mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-02 00:57:59 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.ui.breakpoints;
|
||||
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Jeka
|
||||
*/
|
||||
public class BreakpointNameCellRenderer extends DefaultTableCellRenderer {
|
||||
private final Color myAnyExceptionForeground = new Color(128, 0, 0);
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
setBorder(null);
|
||||
BreakpointTableModel tableModel = (BreakpointTableModel)table.getModel();
|
||||
Breakpoint breakpoint = tableModel.getBreakpoint(row);
|
||||
if (breakpoint == null){
|
||||
return this;
|
||||
};
|
||||
final Icon icon = (breakpoint instanceof BreakpointWithHighlighter)?
|
||||
breakpoint.ENABLED? ((BreakpointWithHighlighter)breakpoint).getSetIcon(false) : ((BreakpointWithHighlighter)breakpoint).getDisabledIcon(
|
||||
false) : breakpoint.getIcon();
|
||||
setIcon(icon);
|
||||
setDisabledIcon(icon);
|
||||
|
||||
if(isSelected){
|
||||
setForeground(UIUtil.getTableSelectionForeground());
|
||||
}
|
||||
else{
|
||||
Color foreColor;
|
||||
if(breakpoint instanceof AnyExceptionBreakpoint){
|
||||
foreColor = myAnyExceptionForeground;
|
||||
}
|
||||
else{
|
||||
foreColor = UIUtil.getTableForeground();
|
||||
}
|
||||
setForeground(foreColor);
|
||||
}
|
||||
setEnabled(isSelected || breakpoint.ENABLED);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.ui.breakpoints;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.ui.Table;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: May 23, 2005
|
||||
*/
|
||||
public class BreakpointTable extends Table {
|
||||
public BreakpointTable(final Project project) {
|
||||
super(new BreakpointTableModel(project));
|
||||
setColumnSelectionAllowed(false);
|
||||
InputMap inputMap = getInputMap();
|
||||
ActionMap actionMap = getActionMap();
|
||||
Object o = inputMap.get(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0));
|
||||
if (o == null) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
o = "enable_disable";
|
||||
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), o);
|
||||
}
|
||||
actionMap.put(o, new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (isEditing()) {
|
||||
return;
|
||||
}
|
||||
int[] indices = getSelectedRows();
|
||||
boolean currentlyMarked = true;
|
||||
for (int i = 0; i < indices.length; i++) {
|
||||
final Boolean isMarked = (Boolean)getValueAt(indices[i], BreakpointTableModel.ENABLED_STATE);
|
||||
currentlyMarked = isMarked != null? isMarked.booleanValue() : false;
|
||||
if (!currentlyMarked) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
final Boolean valueToSet = currentlyMarked ? Boolean.FALSE : Boolean.TRUE;
|
||||
for (int i = 0; i < indices.length; i++) {
|
||||
setValueAt(valueToSet, indices[i], BreakpointTableModel.ENABLED_STATE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setShowGrid(false);
|
||||
setIntercellSpacing(new Dimension(0, 0));
|
||||
setTableHeader(null);
|
||||
setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
|
||||
setColumnSelectionAllowed(false);
|
||||
|
||||
int width = new JCheckBox().getPreferredSize().width;
|
||||
TableColumnModel columnModel = getColumnModel();
|
||||
|
||||
TableColumn enabledStateColumn = columnModel.getColumn(BreakpointTableModel.ENABLED_STATE);
|
||||
enabledStateColumn.setPreferredWidth(width);
|
||||
enabledStateColumn.setMaxWidth(width);
|
||||
final Class enabledStateColumnClass = getModel().getColumnClass(BreakpointTableModel.ENABLED_STATE);
|
||||
final TableCellRenderer delegateRenderer = getDefaultRenderer(enabledStateColumnClass);
|
||||
setDefaultRenderer(enabledStateColumnClass, new DefaultTableCellRenderer() {
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
final Component component = delegateRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
if (component instanceof JComponent) {
|
||||
((JComponent)component).setBorder(null);
|
||||
}
|
||||
return component;
|
||||
}
|
||||
});
|
||||
columnModel.getColumn(BreakpointTableModel.NAME).setCellRenderer(new BreakpointNameCellRenderer());
|
||||
|
||||
getEmptyText().setText(XDebuggerBundle.message("debugger.no.breakpoints"));
|
||||
}
|
||||
|
||||
public BreakpointTableModel getModel() {
|
||||
return (BreakpointTableModel)super.getModel();
|
||||
}
|
||||
|
||||
public void setBreakpoints(Breakpoint[] breakpoints) {
|
||||
getModel().setBreakpoints(breakpoints);
|
||||
}
|
||||
|
||||
public final java.util.List<Breakpoint> getBreakpoints() {
|
||||
return getModel().getBreakpoints();
|
||||
}
|
||||
|
||||
public Breakpoint[] getSelectedBreakpoints() {
|
||||
if (getRowCount() == 0) {
|
||||
return Breakpoint.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
int[] rows = getSelectedRows();
|
||||
if (rows.length == 0) {
|
||||
return Breakpoint.EMPTY_ARRAY;
|
||||
}
|
||||
Breakpoint[] rv = new Breakpoint[rows.length];
|
||||
for (int idx = 0; idx < rows.length; idx++) {
|
||||
rv[idx] = getModel().getBreakpoint(rows[idx]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
-161
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Class BreakpointTableModel
|
||||
* @author Jeka
|
||||
*/
|
||||
package com.intellij.debugger.ui.breakpoints;
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.ItemRemovable;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class BreakpointTableModel extends AbstractTableModel implements ItemRemovable {
|
||||
public static final int ENABLED_STATE = 0;
|
||||
public static final int NAME = 1;
|
||||
|
||||
private java.util.List<Breakpoint> myBreakpoints = null;
|
||||
private final BreakpointManager myBreakpointManager;
|
||||
|
||||
public BreakpointTableModel(final Project project) {
|
||||
myBreakpoints = new ArrayList<Breakpoint>();
|
||||
myBreakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager();
|
||||
}
|
||||
|
||||
public final void setBreakpoints(Breakpoint[] breakpoints) {
|
||||
myBreakpoints.clear();
|
||||
if (breakpoints != null) {
|
||||
ContainerUtil.addAll(myBreakpoints, breakpoints);
|
||||
}
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public List<Breakpoint> getBreakpoints() {
|
||||
return Collections.unmodifiableList(myBreakpoints);
|
||||
}
|
||||
|
||||
public void removeBreakpoints(Breakpoint[] breakpoints) {
|
||||
myBreakpoints.removeAll(Arrays.asList(breakpoints));
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public Breakpoint getBreakpoint(int index) {
|
||||
if (index < 0 || index >= myBreakpoints.size()) return null;
|
||||
return myBreakpoints.get(index);
|
||||
}
|
||||
|
||||
public boolean isBreakpointEnabled(int index) {
|
||||
return ((Boolean)getValueAt(index, ENABLED_STATE)).booleanValue();
|
||||
}
|
||||
|
||||
public int getBreakpointIndex(Breakpoint breakpoint) {
|
||||
return myBreakpoints.indexOf(breakpoint);
|
||||
}
|
||||
|
||||
public void insertBreakpointAt(Breakpoint breakpoint, int index) {
|
||||
myBreakpoints.add(index, breakpoint);
|
||||
fireTableRowsInserted(index, index);
|
||||
}
|
||||
|
||||
public void addBreakpoint(Breakpoint breakpoint) {
|
||||
myBreakpoints.add(breakpoint);
|
||||
int row = myBreakpoints.size() - 1;
|
||||
fireTableRowsInserted(row, row);
|
||||
}
|
||||
|
||||
public void removeRow(int idx) {
|
||||
if (idx >= 0 && idx < myBreakpoints.size()) {
|
||||
myBreakpoints.remove(idx);
|
||||
fireTableRowsDeleted(idx, idx);
|
||||
}
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return myBreakpoints.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public String getColumnName(int column) {
|
||||
switch (column) {
|
||||
case ENABLED_STATE:
|
||||
return DebuggerBundle.message("breakpoint.table.header.column.enabled");
|
||||
case NAME:
|
||||
return DebuggerBundle.message("breakpoint.table.header.column.name");
|
||||
default :
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
Breakpoint breakpoint = myBreakpoints.get(rowIndex);
|
||||
if (columnIndex == NAME) {
|
||||
return breakpoint.getDisplayName();
|
||||
}
|
||||
if (columnIndex == ENABLED_STATE) {
|
||||
return breakpoint.ENABLED? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
if (rowIndex < 0 || rowIndex >= myBreakpoints.size()) {
|
||||
return;
|
||||
}
|
||||
Breakpoint breakpoint = myBreakpoints.get(rowIndex);
|
||||
/*
|
||||
if (columnIndex == NAME) {
|
||||
breakpoint.setDisplayName((aValue != null)? aValue.toString() : "");
|
||||
}
|
||||
else
|
||||
*/
|
||||
if (columnIndex == ENABLED_STATE) {
|
||||
final boolean isEnabled = aValue == null || ((Boolean)aValue).booleanValue();
|
||||
final boolean valueChanged = isEnabled != breakpoint.ENABLED;
|
||||
breakpoint.ENABLED = isEnabled;
|
||||
if (valueChanged) {
|
||||
breakpoint.updateUI();
|
||||
}
|
||||
}
|
||||
fireTableRowsUpdated(rowIndex, rowIndex);
|
||||
}
|
||||
|
||||
public Class getColumnClass(int columnIndex) {
|
||||
if (columnIndex == ENABLED_STATE) {
|
||||
return Boolean.class;
|
||||
}
|
||||
return super.getColumnClass(columnIndex);
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
if (columnIndex != ENABLED_STATE) {
|
||||
return false;
|
||||
}
|
||||
final boolean isSlave = myBreakpointManager.findMasterBreakpoint(myBreakpoints.get(rowIndex)) != null;
|
||||
return !isSlave;
|
||||
}
|
||||
}
|
||||
@@ -1,824 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.ui.breakpoints;
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: May 20, 2005
|
||||
*/
|
||||
public class BreakpointTree extends CheckboxTree {
|
||||
private static final String DEFAULT_PACKAGE_NAME = DebuggerBundle.message("default.package.name");
|
||||
private final CheckedTreeNode myRootNode;
|
||||
private final List<Breakpoint> myBreakpoints = new ArrayList<Breakpoint>();
|
||||
private final Map<TreeDescriptor, CheckedTreeNode> myDescriptorToNodeMap = new HashMap<TreeDescriptor, CheckedTreeNode>();
|
||||
|
||||
private boolean myGroupByMethods = false;
|
||||
private boolean myGroupByClasses = true;
|
||||
private boolean myFlattenPackages = true;
|
||||
|
||||
private final NodeAppender[] myAppenders = {
|
||||
new BreakpointToMethodAppender(),
|
||||
new BreakpointToClassAppender(),
|
||||
new BreakpointToPackageAppender(),
|
||||
new MethodToClassAppender(),
|
||||
new MethodToPackageAppender(),
|
||||
new ClassToPackageAppender(),
|
||||
new PackageToPackageAppender(),
|
||||
};
|
||||
|
||||
private final Comparator<CheckedTreeNode> myNodeComparator = new Comparator<CheckedTreeNode>() {
|
||||
public int compare(CheckedTreeNode o1, CheckedTreeNode o2) {
|
||||
final int w1 = getWeight(o1);
|
||||
final int w2 = getWeight(o2);
|
||||
if (w1 != w2) {
|
||||
return w1 - w2;
|
||||
}
|
||||
final TreeDescriptor d1 = (TreeDescriptor)o1.getUserObject();
|
||||
final TreeDescriptor d2 = (TreeDescriptor)o2.getUserObject();
|
||||
if (d1 instanceof BreakpointDescriptor && d2 instanceof BreakpointDescriptor) {
|
||||
return 0;
|
||||
}
|
||||
return d1.getDisplayString().compareTo(d2.getDisplayString());
|
||||
}
|
||||
|
||||
private int getWeight(CheckedTreeNode node) {
|
||||
if (node.getUserObject() instanceof BreakpointDescriptor) {
|
||||
return 100;
|
||||
}
|
||||
if (node.getUserObject() instanceof MethodDescriptor) {
|
||||
return 90;
|
||||
}
|
||||
if (node.getUserObject() instanceof PackageDescriptor) {
|
||||
return 80;
|
||||
}
|
||||
if (node.getUserObject() instanceof ClassDescriptor) {
|
||||
return 70;
|
||||
}
|
||||
return 50;
|
||||
}
|
||||
};
|
||||
private final BreakpointManager myBreakpointManager;
|
||||
private final BreakpointManagerListener myNodeUpdateListener;
|
||||
|
||||
protected void installSpeedSearch() {
|
||||
new TreeSpeedSearch(this, new Convertor<TreePath, String>() {
|
||||
public String convert(TreePath path) {
|
||||
final CheckedTreeNode node = (CheckedTreeNode)path.getLastPathComponent();
|
||||
return ((TreeDescriptor)node.getUserObject()).getDisplayString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean getExpandsSelectedPaths() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Breakpoint[] getSelectedBreakpoints() {
|
||||
final TreePath[] selectionPaths = getSelectionPaths();
|
||||
if (selectionPaths == null || selectionPaths.length == 0) {
|
||||
return Breakpoint.EMPTY_ARRAY;
|
||||
}
|
||||
final List<Breakpoint> breakpoints = new ArrayList<Breakpoint>(selectionPaths.length);
|
||||
for (TreePath path : selectionPaths) {
|
||||
final CheckedTreeNode node = (CheckedTreeNode)path.getLastPathComponent();
|
||||
TreeUtil.traverseDepth(node, new TreeUtil.Traverse() {
|
||||
public boolean accept(Object _node) {
|
||||
final CheckedTreeNode node = (CheckedTreeNode)_node;
|
||||
final TreeDescriptor descriptor = (TreeDescriptor)node.getUserObject();
|
||||
if (descriptor instanceof BreakpointDescriptor) {
|
||||
breakpoints.add(((BreakpointDescriptor)descriptor).getBreakpoint());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return breakpoints.toArray(new Breakpoint[breakpoints.size()]);
|
||||
}
|
||||
|
||||
public void selectBreakpoint(Breakpoint breakpoint) {
|
||||
final CheckedTreeNode node = myDescriptorToNodeMap.get(new BreakpointDescriptor(breakpoint));
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
TreeUtil.selectNode(this, node);
|
||||
}
|
||||
|
||||
public void selectBreakpoints(Breakpoint[] breakpoints) {
|
||||
final List<CheckedTreeNode> nodes = new ArrayList<CheckedTreeNode>(breakpoints.length);
|
||||
for (Breakpoint breakpoint : breakpoints) {
|
||||
final CheckedTreeNode node = myDescriptorToNodeMap.get(new BreakpointDescriptor(breakpoint));
|
||||
if (node != null) {
|
||||
nodes.add(node);
|
||||
}
|
||||
}
|
||||
clearSelection();
|
||||
for (CheckedTreeNode node : nodes) {
|
||||
addSelectionPath(new TreePath(node.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
public void selectFirstBreakpoint() {
|
||||
TreeUtil.traverseDepth(myRootNode, new TreeUtil.Traverse() {
|
||||
public boolean accept(Object node) {
|
||||
final CheckedTreeNode treeNode = (CheckedTreeNode)node;
|
||||
final TreeDescriptor descriptor = (TreeDescriptor)treeNode.getUserObject();
|
||||
if (descriptor instanceof BreakpointDescriptor) {
|
||||
TreeUtil.selectNode(BreakpointTree.this, treeNode);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<Breakpoint> getBreakpoints() {
|
||||
return Collections.unmodifiableList(myBreakpoints);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
final KeyStroke[] treeStrokes = getRegisteredKeyStrokes();
|
||||
for (KeyStroke stroke : treeStrokes) {
|
||||
unregisterKeyboardAction(stroke);
|
||||
}
|
||||
myBreakpointManager.removeBreakpointManagerListener(myNodeUpdateListener);
|
||||
}
|
||||
|
||||
private abstract static class TreeDescriptor {
|
||||
protected void customizeCellRenderer(final ColoredTreeCellRenderer targetRenderer, CheckedTreeNode node, boolean selected, final boolean checked, boolean expanded, boolean leaf, boolean hasFocus) {
|
||||
targetRenderer.setIcon(getDisplayIcon());
|
||||
targetRenderer.append(getDisplayString(), checked? SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
}
|
||||
|
||||
protected abstract String getDisplayString();
|
||||
|
||||
protected abstract Icon getDisplayIcon();
|
||||
|
||||
}
|
||||
|
||||
private final class BreakpointDescriptor extends TreeDescriptor {
|
||||
private final Breakpoint myBreakpoint;
|
||||
public BreakpointDescriptor(Breakpoint breakpoint) {
|
||||
myBreakpoint = breakpoint;
|
||||
}
|
||||
@NotNull
|
||||
public Breakpoint getBreakpoint() {
|
||||
return myBreakpoint;
|
||||
}
|
||||
|
||||
protected Icon getDisplayIcon() {
|
||||
return myBreakpoint instanceof BreakpointWithHighlighter ?
|
||||
myBreakpoint.ENABLED? ((BreakpointWithHighlighter)myBreakpoint).getSetIcon(false) : ((BreakpointWithHighlighter)myBreakpoint).getDisabledIcon(false) : myBreakpoint.getIcon();
|
||||
}
|
||||
|
||||
public String getDisplayString() {
|
||||
return myBreakpoint.getDisplayName();
|
||||
}
|
||||
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final BreakpointDescriptor breakpointDescriptor = (BreakpointDescriptor)o;
|
||||
return myBreakpoint.equals(breakpointDescriptor.myBreakpoint);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myBreakpoint.hashCode();
|
||||
}
|
||||
|
||||
public boolean isSlave() {
|
||||
final Breakpoint breakpoint = getBreakpoint();
|
||||
return myBreakpointManager.findMasterBreakpoint(breakpoint) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MethodDescriptor extends TreeDescriptor {
|
||||
@NotNull
|
||||
private final String myClassName;
|
||||
@NotNull
|
||||
private final String myMethodName;
|
||||
@NotNull
|
||||
private final String myPackageName;
|
||||
|
||||
public MethodDescriptor(@NotNull String methodName, @NotNull String className, @NotNull String packageName) {
|
||||
myClassName = className;
|
||||
myMethodName = methodName.endsWith("()")? methodName : methodName + "()";
|
||||
myPackageName = packageName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPackageName() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return myClassName;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return myMethodName;
|
||||
}
|
||||
|
||||
protected String getDisplayString() {
|
||||
return myMethodName;
|
||||
}
|
||||
|
||||
protected Icon getDisplayIcon() {
|
||||
return PlatformIcons.METHOD_ICON;
|
||||
}
|
||||
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final MethodDescriptor methodDescriptor = (MethodDescriptor)o;
|
||||
if (!myClassName.equals(methodDescriptor.myClassName)) {
|
||||
return false;
|
||||
}
|
||||
return myMethodName.equals(methodDescriptor.myMethodName);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result = myClassName.hashCode();
|
||||
result = 29 * result + myMethodName.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ClassDescriptor extends TreeDescriptor {
|
||||
@NotNull private final String myClassName;
|
||||
@NotNull private final String myPackageName;
|
||||
|
||||
public ClassDescriptor(@NotNull String className, @NotNull String packageName) {
|
||||
myClassName = className;
|
||||
myPackageName = packageName.length() == 0? DEFAULT_PACKAGE_NAME : packageName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPackageName() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getClassName() {
|
||||
return myClassName;
|
||||
}
|
||||
|
||||
protected String getDisplayString() {
|
||||
return getClassName();
|
||||
}
|
||||
|
||||
protected Icon getDisplayIcon() {
|
||||
return PlatformIcons.CLASS_ICON;
|
||||
}
|
||||
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ClassDescriptor classDescriptor = (ClassDescriptor)o;
|
||||
|
||||
return myClassName.equals(classDescriptor.myClassName);
|
||||
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myClassName.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PackageDescriptor extends TreeDescriptor {
|
||||
private final String myPackageName;
|
||||
|
||||
public PackageDescriptor(String packageName) {
|
||||
myPackageName = "".equals(packageName)? DEFAULT_PACKAGE_NAME : packageName;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
public String getParentPackageName() {
|
||||
final int dotIndex = myPackageName.lastIndexOf('.');
|
||||
return dotIndex >= 0 ? myPackageName.substring(0, dotIndex) : null;
|
||||
}
|
||||
|
||||
public void customizeCellRenderer(final ColoredTreeCellRenderer targetRenderer, CheckedTreeNode node, boolean selected,
|
||||
final boolean checked, boolean expanded, boolean leaf, boolean hasFocus) {
|
||||
targetRenderer.setIcon(PlatformIcons.PACKAGE_ICON);
|
||||
final String displayName;
|
||||
final CheckedTreeNode parent = (CheckedTreeNode)node.getParent();
|
||||
if (parent != null && parent.getUserObject() instanceof PackageDescriptor) {
|
||||
final String parentPackageInTree = ((PackageDescriptor)parent.getUserObject()).getPackageName() + ".";
|
||||
displayName = myPackageName.startsWith(parentPackageInTree)? myPackageName.substring(parentPackageInTree.length()) : myPackageName;
|
||||
}
|
||||
else {
|
||||
displayName = myPackageName;
|
||||
}
|
||||
targetRenderer.append(displayName, checked? SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
}
|
||||
|
||||
protected String getDisplayString() {
|
||||
return myPackageName;
|
||||
}
|
||||
|
||||
protected Icon getDisplayIcon() {
|
||||
return PlatformIcons.PACKAGE_ICON;
|
||||
}
|
||||
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PackageDescriptor packageDescriptor = (PackageDescriptor)o;
|
||||
|
||||
return myPackageName.equals(packageDescriptor.myPackageName);
|
||||
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myPackageName.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public BreakpointTree(final Project project) {
|
||||
super(new BreakpointTreeCellRenderer(), new CheckedTreeNode(new RootDescriptor()));
|
||||
myRootNode = (CheckedTreeNode)getModel().getRoot();
|
||||
myDescriptorToNodeMap.put((TreeDescriptor)myRootNode.getUserObject(), myRootNode);
|
||||
myBreakpointManager = DebuggerManagerEx.getInstanceEx(project).getBreakpointManager();
|
||||
myNodeUpdateListener = new BreakpointManagerListener() {
|
||||
public void breakpointsChanged() {
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
myBreakpointManager.addBreakpointManagerListener(myNodeUpdateListener);
|
||||
getEmptyText().setText(XDebuggerBundle.message("debugger.no.breakpoints"));
|
||||
}
|
||||
|
||||
public boolean isGroupByMethods() {
|
||||
return myGroupByMethods;
|
||||
}
|
||||
|
||||
public void setGroupByMethods(boolean groupByMethods) {
|
||||
if (myGroupByMethods != groupByMethods) {
|
||||
myGroupByMethods = groupByMethods;
|
||||
rebuildTree();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGroupByClasses() {
|
||||
return myGroupByClasses;
|
||||
}
|
||||
|
||||
public void setGroupByClasses(boolean groupByClasses) {
|
||||
if (myGroupByClasses != groupByClasses) {
|
||||
myGroupByClasses = groupByClasses;
|
||||
rebuildTree();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlattenPackages() {
|
||||
return myFlattenPackages;
|
||||
}
|
||||
|
||||
public void setFlattenPackages(boolean flattenPackages) {
|
||||
if (myFlattenPackages != flattenPackages) {
|
||||
myFlattenPackages = flattenPackages;
|
||||
rebuildTree();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNodeStateChanged(final CheckedTreeNode node) {
|
||||
final Object descriptor = node.getUserObject();
|
||||
final Breakpoint breakpoint;
|
||||
if (descriptor instanceof BreakpointDescriptor) {
|
||||
breakpoint = ((BreakpointDescriptor)descriptor).getBreakpoint();
|
||||
if (myBreakpointManager.findMasterBreakpoint(breakpoint) != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
breakpoint = null;
|
||||
}
|
||||
|
||||
if (breakpoint != null) {
|
||||
myBreakpointManager.setBreakpointEnabled(breakpoint, node.isChecked());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addBreakpoint(final Breakpoint breakpoint) {
|
||||
myBreakpoints.add(breakpoint);
|
||||
breakpoint.updateUI(new Runnable() {
|
||||
public void run() {
|
||||
rebuildTree();
|
||||
}
|
||||
});
|
||||
rebuildTree();
|
||||
selectBreakpoint(breakpoint);
|
||||
}
|
||||
|
||||
public void removeBreakpoint(Breakpoint breakpoint) {
|
||||
myBreakpoints.remove(breakpoint);
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
public void removeBreakpoints(Breakpoint[] breakpoints) {
|
||||
myBreakpoints.removeAll(Arrays.asList(breakpoints));
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
public void setBreakpoints(Breakpoint[] breakpoints) {
|
||||
myBreakpoints.clear();
|
||||
ContainerUtil.addAll(myBreakpoints, breakpoints);
|
||||
rebuildTree();
|
||||
}
|
||||
|
||||
public Breakpoint getPreviousSibling(Breakpoint breakpoint) {
|
||||
return getSibling(breakpoint, false);
|
||||
}
|
||||
|
||||
|
||||
public Breakpoint getNextSibling(Breakpoint breakpoint) {
|
||||
return getSibling(breakpoint, true);
|
||||
}
|
||||
|
||||
private Breakpoint getSibling(Breakpoint breakpoint, boolean nextSibling) {
|
||||
final CheckedTreeNode node = myDescriptorToNodeMap.get(new BreakpointDescriptor(breakpoint));
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
final CheckedTreeNode sibling = (CheckedTreeNode) (nextSibling? node.getNextSibling() : node.getPreviousSibling());
|
||||
if (sibling == null) {
|
||||
return null;
|
||||
}
|
||||
final TreeDescriptor descriptor = (TreeDescriptor)sibling.getUserObject();
|
||||
return descriptor instanceof BreakpointDescriptor ? ((BreakpointDescriptor)descriptor).getBreakpoint() : null;
|
||||
}
|
||||
|
||||
private void rebuildTree() {
|
||||
final TreeStateSnapshot treeStateSnapshot = new TreeStateSnapshot(this);
|
||||
myRootNode.removeAllChildren();
|
||||
myDescriptorToNodeMap.clear();
|
||||
myDescriptorToNodeMap.put((TreeDescriptor)myRootNode.getUserObject(), myRootNode);
|
||||
// build tree
|
||||
for (final Breakpoint breakpoint : myBreakpoints) {
|
||||
CheckedTreeNode node = createNode(new BreakpointDescriptor(breakpoint));
|
||||
node.setChecked(breakpoint.ENABLED);
|
||||
addNode(node);
|
||||
}
|
||||
// remove all package nodes with one child
|
||||
final int count = myRootNode.getChildCount();
|
||||
final List<CheckedTreeNode> children = new ArrayList<CheckedTreeNode>();
|
||||
for (int idx = 0; idx < count; idx++) {
|
||||
CheckedTreeNode child = (CheckedTreeNode)myRootNode.getChildAt(idx);
|
||||
if (!(child.getUserObject() instanceof PackageDescriptor)) {
|
||||
children.add(child);
|
||||
continue;
|
||||
}
|
||||
while (child.getUserObject() instanceof PackageDescriptor && child.getChildCount() <= 1) {
|
||||
child = (CheckedTreeNode)child.getChildAt(0);
|
||||
}
|
||||
if (!(child.getUserObject() instanceof PackageDescriptor)) {
|
||||
child = (CheckedTreeNode)child.getParent();
|
||||
}
|
||||
for (CheckedTreeNode childToRemove = (CheckedTreeNode)child.getParent(); !childToRemove.equals(myRootNode); childToRemove = (CheckedTreeNode)childToRemove.getParent()) {
|
||||
myDescriptorToNodeMap.remove(childToRemove.getUserObject());
|
||||
}
|
||||
children.add(child);
|
||||
}
|
||||
for (final CheckedTreeNode aChildren : children) {
|
||||
aChildren.removeFromParent();
|
||||
}
|
||||
myRootNode.removeAllChildren();
|
||||
for (final CheckedTreeNode child : children) {
|
||||
myRootNode.add(child);
|
||||
}
|
||||
sortChildren(myRootNode);
|
||||
((DefaultTreeModel)getModel()).nodeStructureChanged(myRootNode);
|
||||
treeStateSnapshot.restore(this);
|
||||
expandPath(new TreePath(myRootNode));
|
||||
}
|
||||
|
||||
private void sortChildren(CheckedTreeNode node) {
|
||||
final int childCount = node.getChildCount();
|
||||
if (childCount == 0) {
|
||||
return;
|
||||
}
|
||||
final List<CheckedTreeNode> children = new ArrayList<CheckedTreeNode>(childCount);
|
||||
for (int idx = 0; idx < childCount; idx++) {
|
||||
children.add((CheckedTreeNode)node.getChildAt(idx));
|
||||
}
|
||||
for (CheckedTreeNode child : children) {
|
||||
sortChildren(child);
|
||||
child.removeFromParent();
|
||||
}
|
||||
Collections.sort(children, myNodeComparator);
|
||||
for (CheckedTreeNode child : children) {
|
||||
node.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CheckedTreeNode createNode(final TreeDescriptor descriptor) {
|
||||
final CheckedTreeNode node = new CheckedTreeNode(descriptor);
|
||||
myDescriptorToNodeMap.put(descriptor, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
*/
|
||||
private void addNode(CheckedTreeNode node) {
|
||||
for (final NodeAppender appender : myAppenders) {
|
||||
node = appender.append(node);
|
||||
if (node == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (node != null) {
|
||||
attachNodeToParent(getDescriptor(myRootNode), node);
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeDescriptor getDescriptor(final CheckedTreeNode node) {
|
||||
return (TreeDescriptor)node.getUserObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parentDescriptor a descriptor of the childNode (possibly not existing) to attach to
|
||||
* @param childNode the childNode to be attached
|
||||
* @return either parent node if it has just been created or null, if the node has been attached to already existing childNode
|
||||
*/
|
||||
private CheckedTreeNode attachNodeToParent(final TreeDescriptor parentDescriptor, final CheckedTreeNode childNode) {
|
||||
CheckedTreeNode parentNode = myDescriptorToNodeMap.get(parentDescriptor);
|
||||
try {
|
||||
if (parentNode != null) {
|
||||
parentNode.add(childNode);
|
||||
return null; // added to already existing, so stop iteration over appenders
|
||||
}
|
||||
parentNode = createNode(parentDescriptor);
|
||||
parentNode.add(childNode);
|
||||
return parentNode;
|
||||
}
|
||||
finally {
|
||||
if (parentNode != null && parentNode.getChildCount() == 1) {
|
||||
expandPath(new TreePath(parentNode.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class BreakpointTreeCellRenderer extends CheckboxTreeCellRenderer {
|
||||
public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (value instanceof CheckedTreeNode) {
|
||||
final CheckedTreeNode node = (CheckedTreeNode)value;
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
descriptor.customizeCellRenderer(getTextRenderer(), node, selected, node.isChecked(), expanded, leaf, hasFocus);
|
||||
if (descriptor instanceof BreakpointDescriptor) {
|
||||
myCheckbox.setEnabled(node.isEnabled() && !((BreakpointDescriptor)descriptor).isSlave());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class NodeAppender {
|
||||
public abstract CheckedTreeNode append(CheckedTreeNode node);
|
||||
}
|
||||
|
||||
private class BreakpointToMethodAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
if (!myGroupByMethods) {
|
||||
return node;
|
||||
}
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof BreakpointDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
final Breakpoint breakpoint = ((BreakpointDescriptor)descriptor).getBreakpoint();
|
||||
if (!(breakpoint instanceof LineBreakpoint)) {
|
||||
return node;
|
||||
}
|
||||
final LineBreakpoint lineBreakpoint = (LineBreakpoint)breakpoint;
|
||||
final String methodName = lineBreakpoint.getMethodName();
|
||||
final String className = lineBreakpoint.getShortClassName();
|
||||
final String packageName = lineBreakpoint.getPackageName();
|
||||
if (methodName == null || className == null || packageName == null) {
|
||||
return node;
|
||||
}
|
||||
return attachNodeToParent(new MethodDescriptor(methodName, className, packageName), node);
|
||||
}
|
||||
}
|
||||
|
||||
private class BreakpointToClassAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
if (!myGroupByClasses) {
|
||||
return node;
|
||||
}
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof BreakpointDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
final Breakpoint breakpoint = ((BreakpointDescriptor)descriptor).getBreakpoint();
|
||||
final String className = breakpoint.getShortClassName();
|
||||
if (className == null) {
|
||||
return node;
|
||||
}
|
||||
final String packageName = breakpoint.getPackageName();
|
||||
if (packageName == null) {
|
||||
return node;
|
||||
}
|
||||
return attachNodeToParent(new ClassDescriptor(className, packageName), node);
|
||||
}
|
||||
}
|
||||
|
||||
private class BreakpointToPackageAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof BreakpointDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
final Breakpoint breakpoint = ((BreakpointDescriptor)descriptor).getBreakpoint();
|
||||
final String packageName;
|
||||
if (breakpoint instanceof ExceptionBreakpoint) {
|
||||
packageName = breakpoint.getPackageName();
|
||||
}
|
||||
else if (breakpoint instanceof BreakpointWithHighlighter) {
|
||||
packageName = breakpoint.getPackageName();
|
||||
}
|
||||
else {
|
||||
packageName = null;
|
||||
}
|
||||
if (packageName == null) {
|
||||
return node;
|
||||
}
|
||||
return attachNodeToParent(new PackageDescriptor(packageName), node);
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodToClassAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
if (!myGroupByClasses) {
|
||||
return node;
|
||||
}
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof MethodDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
final MethodDescriptor methodDescriptor = (MethodDescriptor)descriptor;
|
||||
final String className = methodDescriptor.getClassName();
|
||||
final String packageName = methodDescriptor.getPackageName();
|
||||
return attachNodeToParent(new ClassDescriptor(className, packageName), node);
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodToPackageAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof MethodDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
final MethodDescriptor methodDescriptor = (MethodDescriptor)descriptor;
|
||||
final String packageName = methodDescriptor.getPackageName();
|
||||
return attachNodeToParent(new PackageDescriptor(packageName), node);
|
||||
}
|
||||
}
|
||||
|
||||
private class ClassToPackageAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
final String packageName = ((ClassDescriptor)descriptor).getPackageName();
|
||||
return attachNodeToParent(new PackageDescriptor(packageName), node);
|
||||
}
|
||||
}
|
||||
|
||||
private class PackageToPackageAppender extends NodeAppender {
|
||||
public CheckedTreeNode append(CheckedTreeNode node) {
|
||||
if (myFlattenPackages) {
|
||||
return node;
|
||||
}
|
||||
final TreeDescriptor descriptor = getDescriptor(node);
|
||||
if (!(descriptor instanceof PackageDescriptor)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
final PackageDescriptor packageDescriptor = (PackageDescriptor)descriptor;
|
||||
final String parentPackageName = packageDescriptor.getParentPackageName();
|
||||
if (parentPackageName == null) {
|
||||
return node;
|
||||
}
|
||||
final CheckedTreeNode parentNode = attachNodeToParent(new PackageDescriptor(parentPackageName), node);
|
||||
if (parentNode == null) {
|
||||
return null;
|
||||
}
|
||||
return append(parentNode);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RootDescriptor extends TreeDescriptor {
|
||||
|
||||
protected String getDisplayString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected Icon getDisplayIcon() {
|
||||
return PlatformIcons.PROJECT_ICON;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TreeStateSnapshot {
|
||||
private final Object[] myExpandedUserObjects;
|
||||
private final Object[] mySelectedUserObjects;
|
||||
|
||||
public TreeStateSnapshot(BreakpointTree tree) {
|
||||
final List<TreePath> expandedPaths = TreeUtil.collectExpandedPaths(tree);
|
||||
myExpandedUserObjects = getUserObjects(expandedPaths.toArray(new TreePath[expandedPaths.size()]));
|
||||
mySelectedUserObjects =getUserObjects(tree.getSelectionPaths());
|
||||
}
|
||||
|
||||
private static Object[] getUserObjects(final TreePath[] treePaths) {
|
||||
if (treePaths == null) {
|
||||
return ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
Object[] userObjects = new Object[treePaths.length];
|
||||
int index = 0;
|
||||
for (TreePath path : treePaths) {
|
||||
userObjects[index++] = ((CheckedTreeNode)path.getLastPathComponent()).getUserObject();
|
||||
}
|
||||
return userObjects;
|
||||
}
|
||||
|
||||
public void restore(BreakpointTree tree) {
|
||||
final List<TreePath> pathsToExpand = getPaths(tree, myExpandedUserObjects);
|
||||
if (!pathsToExpand.isEmpty()) {
|
||||
TreeUtil.restoreExpandedPaths(tree, pathsToExpand);
|
||||
}
|
||||
|
||||
final List<TreePath> pathsToSelect = getPaths(tree, mySelectedUserObjects);
|
||||
if (!pathsToSelect.isEmpty()) {
|
||||
tree.getSelectionModel().clearSelection();
|
||||
tree.setSelectionPaths(pathsToSelect.toArray(new TreePath[pathsToSelect.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
private static List<TreePath> getPaths(BreakpointTree tree, final Object[] userObjects) {
|
||||
final List<TreePath> paths = new ArrayList<TreePath>(userObjects.length);
|
||||
for (Object descriptor : userObjects) {
|
||||
final CheckedTreeNode node = tree.myDescriptorToNodeMap.get(descriptor);
|
||||
if (node != null) {
|
||||
paths.add(new TreePath(node.getPath()));
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.miscGenerics;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -150,6 +151,7 @@ public class RedundantTypeArgsInspection extends GenericsInspectionToolBase {
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiReferenceParameterList typeArgumentList = (PsiReferenceParameterList)descriptor.getPsiElement();
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(typeArgumentList)) return;
|
||||
try {
|
||||
final PsiMethodCallExpression expr =
|
||||
(PsiMethodCallExpression)JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText("foo()", null);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.externalSystem;
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.Key;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
@@ -105,9 +106,9 @@ public class JavaProjectDataService implements ProjectDataService<JavaProjectDat
|
||||
if (languageLevelExtension.getLanguageLevel().isAtLeast(languageLevel)) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
languageLevelExtension.setLanguageLevel(languageLevel);
|
||||
}
|
||||
});
|
||||
|
||||
+10
@@ -102,6 +102,16 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
final PsiReferenceParameterList parameterList = getParameterList();
|
||||
return parameterList != null && parameterList.getTypeParameterElements().length > 0 ? psiMethod : null;
|
||||
}
|
||||
if (containingClass.hasTypeParameters()) {
|
||||
final PsiElement qualifier = getQualifier();
|
||||
if (qualifier instanceof PsiTypeElement) {
|
||||
final PsiJavaCodeReferenceElement referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
|
||||
if (referenceElement != null) {
|
||||
final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
|
||||
return parameterList != null && parameterList.getTypeParameterElements().length > 0 ? psiMethod : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return psiMethod;
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.externalSystem.util;
|
||||
|
||||
import com.intellij.openapi.components.ComponentManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Vladislav.Soroka
|
||||
* @since 11/6/13
|
||||
*/
|
||||
public abstract class DisposeAwareProjectChange implements Runnable {
|
||||
private final ComponentManager myComponentManager;
|
||||
|
||||
protected DisposeAwareProjectChange(@NotNull ComponentManager componentManager) {
|
||||
myComponentManager = componentManager;
|
||||
}
|
||||
|
||||
public abstract void execute();
|
||||
|
||||
public final void run() {
|
||||
if (!myComponentManager.isDisposed()) {
|
||||
execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -323,11 +323,11 @@ public class ExternalSystemApiUtil {
|
||||
return result == null ? Collections.<DataNode<T>>emptyList() : result;
|
||||
}
|
||||
|
||||
public static void executeProjectChangeAction(@NotNull final Runnable task) {
|
||||
public static void executeProjectChangeAction(@NotNull final DisposeAwareProjectChange task) {
|
||||
executeProjectChangeAction(false, task);
|
||||
}
|
||||
|
||||
public static void executeProjectChangeAction(boolean synchronous, @NotNull final Runnable task) {
|
||||
public static void executeProjectChangeAction(boolean synchronous, @NotNull final DisposeAwareProjectChange task) {
|
||||
executeOnEdt(synchronous, new Runnable() {
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
|
||||
+3
-2
@@ -10,6 +10,7 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
@@ -74,9 +75,9 @@ public class RefreshExternalProjectAction extends AnAction implements DumbAware,
|
||||
if (externalProject == null) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+3
-2
@@ -29,6 +29,7 @@ import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefres
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
@@ -87,9 +88,9 @@ public class ExternalSystemAutoImporter implements BulkFileListener, DocumentLis
|
||||
@Override
|
||||
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
|
||||
if (externalProject != null) {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(myProject) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(myProject).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+7
-6
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.externalSystem.service.project.manage;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.project.AbstractDependencyData;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
@@ -39,9 +40,9 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
|
||||
{
|
||||
|
||||
public void setScope(@NotNull final DependencyScope scope, @NotNull final ExportableOrderEntry dependency, boolean synchronous) {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(dependency.getOwnerModule()) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
doForDependency(dependency, new Consumer<ExportableOrderEntry>() {
|
||||
@Override
|
||||
public void consume(ExportableOrderEntry entry) {
|
||||
@@ -53,9 +54,9 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
|
||||
}
|
||||
|
||||
public void setExported(final boolean exported, @NotNull final ExportableOrderEntry dependency, boolean synchronous) {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(dependency.getOwnerModule()) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
doForDependency(dependency, new Consumer<ExportableOrderEntry>() {
|
||||
@Override
|
||||
public void consume(ExportableOrderEntry entry) {
|
||||
@@ -116,9 +117,9 @@ public abstract class AbstractDependencyDataService<E extends AbstractDependency
|
||||
return;
|
||||
}
|
||||
for (final ExportableOrderEntry dependency : toRemove) {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(dependency.getOwnerModule()) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
||||
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
|
||||
try {
|
||||
|
||||
+3
-2
@@ -8,6 +8,7 @@ import com.intellij.openapi.externalSystem.model.project.ContentRootData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
@@ -81,9 +82,9 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
|
||||
@NotNull final Module module,
|
||||
boolean synchronous)
|
||||
{
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
||||
final ModifiableRootModel model = moduleRootManager.getModifiableModel();
|
||||
final ContentEntry[] contentEntries = model.getContentEntries();
|
||||
|
||||
+9
-8
@@ -9,6 +9,7 @@ import com.intellij.openapi.externalSystem.model.project.LibraryPathType;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalLibraryPathTypeMapper;
|
||||
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
@@ -78,7 +79,7 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
|
||||
Library library = myProjectStructureHelper.findIdeLibrary(toImport, project);
|
||||
if (library != null) {
|
||||
syncPaths(toImport, library, synchronous);
|
||||
syncPaths(toImport, library, project, synchronous);
|
||||
return;
|
||||
}
|
||||
importLibrary(toImport.getName(), libraryFiles, project, synchronous);
|
||||
@@ -102,9 +103,9 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
@NotNull final Project project,
|
||||
boolean synchronous)
|
||||
{
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
// Is assumed to be called from the EDT.
|
||||
final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project);
|
||||
final LibraryTable.ModifiableModel projectLibraryModel = libraryTable.getModifiableModel();
|
||||
@@ -165,9 +166,9 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
if (libraries.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project);
|
||||
final LibraryTable.ModifiableModel model = libraryTable.getModifiableModel();
|
||||
try {
|
||||
@@ -188,7 +189,7 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
});
|
||||
}
|
||||
|
||||
public void syncPaths(@NotNull final LibraryData externalLibrary, @NotNull final Library ideLibrary, boolean synchronous) {
|
||||
public void syncPaths(@NotNull final LibraryData externalLibrary, @NotNull final Library ideLibrary, @NotNull final Project project, boolean synchronous) {
|
||||
if (externalLibrary.isUnresolved()) {
|
||||
return;
|
||||
}
|
||||
@@ -212,9 +213,9 @@ public class LibraryDataService implements ProjectDataService<LibraryData, Libra
|
||||
if (toRemove.isEmpty() && toAdd.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
Library.ModifiableModel model = ideLibrary.getModifiableModel();
|
||||
try {
|
||||
for (Map.Entry<OrderRootType, Set<String>> entry : toRemove.entrySet()) {
|
||||
|
||||
+3
-2
@@ -22,6 +22,7 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.openapi.externalSystem.model.project.*;
|
||||
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
@@ -100,9 +101,9 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
|
||||
@NotNull final Module module,
|
||||
final boolean synchronous)
|
||||
{
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
importMissingProjectLibraries(module, nodesToImport, synchronous);
|
||||
|
||||
// The general idea is to import all external project library dependencies and module libraries which don't present at the
|
||||
|
||||
+9
-8
@@ -10,6 +10,7 @@ import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceTyp
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
@@ -72,9 +73,9 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
|
||||
myAlarm.addRequest(new ImportModulesTask(project, toImport, synchronous), PROJECT_INITIALISATION_DELAY_MS);
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
final Collection<DataNode<ModuleData>> toCreate = filterExistingModules(toImport, project);
|
||||
if (!toCreate.isEmpty()) {
|
||||
createModules(toCreate, project);
|
||||
@@ -90,7 +91,7 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
|
||||
}
|
||||
|
||||
private void createModules(@NotNull final Collection<DataNode<ModuleData>> toCreate, @NotNull final Project project) {
|
||||
removeExistingModulesConfigs(toCreate);
|
||||
removeExistingModulesConfigs(toCreate, project);
|
||||
Application application = ApplicationManager.getApplication();
|
||||
final Map<DataNode<ModuleData>, Module> moduleMappings = ContainerUtilRt.newHashMap();
|
||||
application.runWriteAction(new Runnable() {
|
||||
@@ -162,13 +163,13 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
|
||||
return result;
|
||||
}
|
||||
|
||||
private void removeExistingModulesConfigs(@NotNull final Collection<DataNode<ModuleData>> nodes) {
|
||||
private void removeExistingModulesConfigs(@NotNull final Collection<DataNode<ModuleData>> nodes, @NotNull final Project project) {
|
||||
if (nodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
|
||||
for (DataNode<ModuleData> node : nodes) {
|
||||
// Remove existing '*.iml' file if necessary.
|
||||
@@ -218,9 +219,9 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
|
||||
if (modules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
for (Module module : modules) {
|
||||
ModuleManager moduleManager = ModuleManager.getInstance(module.getProject());
|
||||
String path = module.getModuleFilePath();
|
||||
|
||||
+3
-2
@@ -23,6 +23,7 @@ import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
@@ -88,9 +89,9 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService<M
|
||||
@NotNull final Module module,
|
||||
final boolean synchronous)
|
||||
{
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
||||
Map<Pair<String /* dependency module name */, /* dependency module scope */DependencyScope> , ModuleOrderEntry> toRemove = ContainerUtilRt.newHashMap();
|
||||
for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
|
||||
|
||||
+3
-6
@@ -20,10 +20,7 @@ import com.intellij.openapi.externalSystem.model.Key;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.externalSystem.util.Order;
|
||||
import com.intellij.openapi.externalSystem.util.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -73,9 +70,9 @@ public class ProjectDataServiceImpl implements ProjectDataService<ProjectData, P
|
||||
if (!(project instanceof ProjectEx) || newName.equals(project.getName())) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
String oldName = project.getName();
|
||||
((ProjectEx)project).setProjectName(newName);
|
||||
ExternalSystemApiUtil.getSettings(project, externalSystemId).getPublisher().onProjectRenamed(oldName, newName);
|
||||
|
||||
+5
-6
@@ -7,15 +7,14 @@ import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter;
|
||||
import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolveProjectTask;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl;
|
||||
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
@@ -135,9 +134,9 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
|
||||
if (externalProjectNode != null) {
|
||||
ExternalSystemUtil.ensureToolWindowInitialized(project, myExternalSystemId);
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -210,9 +209,9 @@ public abstract class AbstractExternalProjectImportBuilder<C extends AbstractImp
|
||||
* dependencies information available at the given gradle project
|
||||
*/
|
||||
private void setupLibraries(@NotNull final DataNode<ProjectData> projectWithResolvedLibraries, final Project project) {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+5
-8
@@ -33,16 +33,13 @@ import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExe
|
||||
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter;
|
||||
import com.intellij.openapi.externalSystem.service.ImportCanceledException;
|
||||
import com.intellij.openapi.externalSystem.service.execution.AbstractExternalSystemTaskConfigurationType;
|
||||
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration;
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
|
||||
import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolveProjectTask;
|
||||
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemIdeNotificationManager;
|
||||
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationExtension;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.PlatformFacade;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService;
|
||||
@@ -76,7 +73,6 @@ import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -211,9 +207,9 @@ public class ExternalSystemUtil {
|
||||
for (DataNode<ModuleData> node : moduleNodes) {
|
||||
myExternalModulePaths.add(node.getData().getLinkedExternalProjectPath());
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -449,6 +445,7 @@ public class ExternalSystemUtil {
|
||||
if (stamp > 0) {
|
||||
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(externalSystemId);
|
||||
assert manager != null;
|
||||
if(project.isDisposed()) return;
|
||||
manager.getLocalSettingsProvider().fun(project).getExternalConfigModificationStamps().put(externalProjectPath, stamp);
|
||||
}
|
||||
DataNode<ProjectData> externalProject = task.getExternalProject();
|
||||
@@ -697,9 +694,9 @@ public class ExternalSystemUtil {
|
||||
projects.add(projectSettings);
|
||||
systemSettings.setLinkedProjectsSettings(projects);
|
||||
ensureToolWindowInitialized(project, externalSystemId);
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+10
-4
@@ -23,6 +23,7 @@ import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ex.ProjectRootManagerEx
|
||||
@@ -151,10 +152,15 @@ abstract class AbstractExternalSystemTest extends UsefulTestCase {
|
||||
def settings = ExternalSystemApiUtil.getSettings(project, ExternalSystemTestUtil.TEST_EXTERNAL_SYSTEM_ID)
|
||||
settings.linkedProjectsSettings = [new TestExternalProjectSettings(externalProjectPath: node.data.linkedExternalProjectPath)]
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring {
|
||||
dataManager.importData(node.key, [node], project, true)
|
||||
} })
|
||||
|
||||
final Project myProject = project
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(myProject) {
|
||||
@Override
|
||||
void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(myProject).mergeRootsChangesDuring {
|
||||
dataManager.importData(node.key, [node], myProject, true)
|
||||
}
|
||||
}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 393 B |
Binary file not shown.
|
After Width: | Height: | Size: 716 B |
Binary file not shown.
|
After Width: | Height: | Size: 857 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 491 B |
Binary file not shown.
|
After Width: | Height: | Size: 929 B |
@@ -32,6 +32,8 @@ public interface Lookup {
|
||||
char COMPLETE_STATEMENT_SELECT_CHAR = '\r';
|
||||
char AUTO_INSERT_SELECT_CHAR = (char) 0;
|
||||
|
||||
int getLookupStart();
|
||||
|
||||
@Nullable
|
||||
LookupElement getCurrentItem();
|
||||
|
||||
|
||||
+2
-1
@@ -208,7 +208,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
try {
|
||||
final int selectionEndOffset = initContext.getSelectionEndOffset();
|
||||
final PsiReference reference = initContext.getFile().findReferenceAt(selectionEndOffset);
|
||||
if (reference != null) {
|
||||
if (reference != null &&
|
||||
reference.getElement().getTextRange().getStartOffset() + reference.getRangeInElement().getStartOffset() != selectionEndOffset) {
|
||||
initContext.setReplacementOffset(findReplacementOffset(selectionEndOffset, reference));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -36,7 +36,6 @@ import java.util.List;
|
||||
* @author Gregory.Shrago
|
||||
*/
|
||||
public abstract class BraceMatcherBasedSelectioner extends ExtendWordSelectionHandlerBase {
|
||||
|
||||
@Override
|
||||
public List<TextRange> select(final PsiElement e, final CharSequence editorText, final int cursorOffset, final Editor editor) {
|
||||
final VirtualFile file = e.getContainingFile().getVirtualFile();
|
||||
@@ -60,8 +59,8 @@ public abstract class BraceMatcherBasedSelectioner extends ExtendWordSelectionHa
|
||||
result.addAll(expandToWholeLine(editorText, new TextRange(last.first, iterator.getEnd())));
|
||||
int bodyStart = last.second;
|
||||
int bodyEnd = iterator.getStart();
|
||||
while (bodyStart < textLength && Character.isWhitespace(editorText.charAt(bodyStart))) bodyStart ++;
|
||||
while (bodyEnd > 0 && Character.isWhitespace(editorText.charAt(bodyEnd - 1))) bodyEnd --;
|
||||
while (bodyStart < textLength && Character.isWhitespace(editorText.charAt(bodyStart))) bodyStart++;
|
||||
while (bodyEnd > 0 && bodyStart < bodyEnd && Character.isWhitespace(editorText.charAt(bodyEnd - 1))) bodyEnd--;
|
||||
result.addAll(expandToWholeLine(editorText, new TextRange(bodyStart, bodyEnd)));
|
||||
}
|
||||
iterator.advance();
|
||||
@@ -69,5 +68,4 @@ public abstract class BraceMatcherBasedSelectioner extends ExtendWordSelectionHa
|
||||
result.add(e.getTextRange());
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import com.intellij.lang.documentation.DocumentationProvider;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
@@ -451,7 +450,7 @@ public class EnterHandler extends BaseEnterHandler {
|
||||
}
|
||||
|
||||
if ((commentContext.docAsterisk || commentContext.slashSlash) && !commentContext.docStart) {
|
||||
myCaretAdvance += commentContext.slashSlash ? commentContext.commenter.getLineCommentPrefix().length() : 1;
|
||||
myCaretAdvance += commentContext.slashSlash ? commentContext.commenter.getLineCommentPrefix().trim().length() : 1;
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
|
||||
-1
@@ -48,7 +48,6 @@ public class EnterInLineCommentHandler extends EnterHandlerDelegateAdapter {
|
||||
if (offset < document.getTextLength() && text.charAt(offset) != '\n') {
|
||||
String prefix = commenter.getLineCommentPrefix();
|
||||
assert prefix != null: "Line Comment type is set but Line Comment Prefix is null!";
|
||||
prefix = prefix.trim();
|
||||
if (!StringUtil.startsWith(text, offset, prefix)) {
|
||||
if (text.charAt(caretOffset) != ' ' && !prefix.endsWith(" ")) {
|
||||
prefix += " ";
|
||||
|
||||
@@ -737,6 +737,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
return lookupString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLookupStart() {
|
||||
return myOffsets.getLookupStart(disposeTrace);
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class FileReferenceCharFilter extends CharFilter{
|
||||
public Result acceptChar(char c, int prefixLength, Lookup lookup) {
|
||||
final LookupElement item = lookup.getCurrentItem();
|
||||
if ('.' == c && item != null && item.getObject() instanceof PsiFileSystemItem) {
|
||||
PsiReference referenceAtCaret = lookup.getPsiFile().findReferenceAt(lookup.getEditor().getCaretModel().getOffset() - 1);
|
||||
PsiReference referenceAtCaret = lookup.getPsiFile().findReferenceAt(lookup.getLookupStart());
|
||||
if (referenceAtCaret != null && FileReference.findFileReference(referenceAtCaret) != null) {
|
||||
return Result.ADD_TO_PREFIX;
|
||||
}
|
||||
|
||||
+15
-12
@@ -132,18 +132,7 @@ public abstract class AutomaticRenamer {
|
||||
final PsiNamedElement element = myElements.get(varIndex);
|
||||
final String name = element.getName();
|
||||
if (!myRenames.containsKey(element)) {
|
||||
String newName;
|
||||
if (oldClassName.equals(name)) {
|
||||
newName = newClassName;
|
||||
} else {
|
||||
String canonicalName = nameToCanonicalName(name, element);
|
||||
final String newCanonicalName = suggester.suggestName(canonicalName);
|
||||
if (newCanonicalName.length() == 0) {
|
||||
LOG.error("oldClassName = " + oldClassName + ", newClassName = " + newClassName + ", name = " + name + ", canonicalName = " +
|
||||
canonicalName + ", newCanonicalName = " + newCanonicalName);
|
||||
}
|
||||
newName = canonicalNameToName(newCanonicalName, element);
|
||||
}
|
||||
String newName = suggestNameForElement(element, suggester, newClassName, oldClassName);
|
||||
if (!newName.equals(name)) {
|
||||
myRenames.put(element, newName);
|
||||
}
|
||||
@@ -157,6 +146,20 @@ public abstract class AutomaticRenamer {
|
||||
}
|
||||
}
|
||||
|
||||
protected String suggestNameForElement(PsiNamedElement element, NameSuggester suggester, String newClassName, String oldClassName) {
|
||||
String name = element.getName();
|
||||
if (oldClassName.equals(name)) {
|
||||
return newClassName;
|
||||
}
|
||||
String canonicalName = nameToCanonicalName(name, element);
|
||||
final String newCanonicalName = suggester.suggestName(canonicalName);
|
||||
if (newCanonicalName.length() == 0) {
|
||||
LOG.error("oldClassName = " + oldClassName + ", newClassName = " + newClassName + ", name = " + name + ", canonicalName = " +
|
||||
canonicalName + ", newCanonicalName = " + newCanonicalName);
|
||||
}
|
||||
return canonicalNameToName(newCanonicalName, element);
|
||||
}
|
||||
|
||||
@NonNls
|
||||
protected String canonicalNameToName(@NonNls String canonicalName, PsiNamedElement element) {
|
||||
return canonicalName;
|
||||
|
||||
@@ -562,6 +562,7 @@ public class JBTabsImpl extends JComponent
|
||||
if (!mySingleRowLayout.isTabHidden(each)) continue;
|
||||
final JBMenuItem item = new JBMenuItem(each.getText(), each.getIcon());
|
||||
item.setForeground(each.getDefaultForeground());
|
||||
item.setBackground(each.getTabColor());
|
||||
mySingleRowLayout.myMorePopup.add(item);
|
||||
item.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
skip: *
|
||||
+4
-1
@@ -48,6 +48,7 @@ import java.nio.charset.Charset;
|
||||
public abstract class VirtualFileSystemEntry extends NewVirtualFile {
|
||||
public static final VirtualFileSystemEntry[] EMPTY_ARRAY = new VirtualFileSystemEntry[0];
|
||||
|
||||
@NonNls protected static final String FS_ROOT_FAKE_NAME = "";
|
||||
protected static final PersistentFS ourPersistence = PersistentFS.getInstance();
|
||||
|
||||
private static final Key<String> SYMLINK_TARGET = Key.create("local.vfs.symlink.target");
|
||||
@@ -73,7 +74,9 @@ public abstract class VirtualFileSystemEntry extends NewVirtualFile {
|
||||
myParent = parent;
|
||||
myId = id;
|
||||
|
||||
storeName(name);
|
||||
if (name != FS_ROOT_FAKE_NAME) {
|
||||
storeName(name);
|
||||
}
|
||||
|
||||
if (parent != null && parent != VirtualDirectoryImpl.NULL_VIRTUAL_FILE) {
|
||||
setFlagInt(IS_SYMLINK_FLAG, PersistentFS.isSymLink(attributes));
|
||||
|
||||
+54
-37
@@ -440,12 +440,11 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile copyFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent, @NotNull final String copyName)
|
||||
throws IOException {
|
||||
getDelegate(file).copyFile(requestor, file, newParent, copyName);
|
||||
processEvent(new VFileCopyEvent(requestor, file, newParent, copyName));
|
||||
public VirtualFile copyFile(Object requestor, @NotNull VirtualFile file, @NotNull VirtualFile parent, @NotNull String name) throws IOException {
|
||||
getDelegate(file).copyFile(requestor, file, parent, name);
|
||||
processEvent(new VFileCopyEvent(requestor, file, parent, name));
|
||||
|
||||
final VirtualFile child = newParent.findChild(copyName);
|
||||
final VirtualFile child = parent.findChild(name);
|
||||
if (child == null) {
|
||||
throw new IOException("Cannot create child");
|
||||
}
|
||||
@@ -453,7 +452,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile createChildDirectory(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String dir) throws IOException {
|
||||
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile parent, @NotNull String dir) throws IOException {
|
||||
getDelegate(parent).createChildDirectory(requestor, parent, dir);
|
||||
processEvent(new VFileCreateEvent(requestor, parent, dir, true, false));
|
||||
|
||||
@@ -465,7 +464,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile createChildFile(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String file) throws IOException {
|
||||
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile parent, @NotNull String file) throws IOException {
|
||||
getDelegate(parent).createChildFile(requestor, parent, file);
|
||||
processEvent(new VFileCreateEvent(requestor, parent, file, false, false));
|
||||
|
||||
@@ -588,8 +587,10 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
return len;
|
||||
}
|
||||
|
||||
private InputStream createReplicator(@NotNull final VirtualFile file, final InputStream nativeStream, final long fileLength, final boolean readOnly)
|
||||
throws IOException {
|
||||
private InputStream createReplicator(@NotNull final VirtualFile file,
|
||||
final InputStream nativeStream,
|
||||
final long fileLength,
|
||||
final boolean readOnly) throws IOException {
|
||||
if (nativeStream instanceof BufferExposingByteArrayInputStream) {
|
||||
// optimization
|
||||
BufferExposingByteArrayInputStream byteStream = (BufferExposingByteArrayInputStream )nativeStream;
|
||||
@@ -931,29 +932,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
root = new JarRoot(fs, rootId, parentLocalFile);
|
||||
}
|
||||
else {
|
||||
root = new VirtualDirectoryImpl(basePath, null, fs, rootId, 0){
|
||||
@Override
|
||||
protected char[] appendPathOnFileSystem(int pathLength, int[] position) {
|
||||
// do not call super method since we know it's the root
|
||||
String name = getName();
|
||||
int nameLength = name.length();
|
||||
boolean appendSlash = SystemInfo.isWindows && nameLength == 2 && name.charAt(1) == ':'
|
||||
&& pathLength == 0 // otherwise we called this as a part of longer file path calculation and slash will be added anyway
|
||||
;
|
||||
|
||||
int rootPathLength = pathLength + nameLength;
|
||||
if (appendSlash) ++rootPathLength;
|
||||
char[] chars = new char[rootPathLength];
|
||||
|
||||
position[0] = copyString(chars, position[0], name);
|
||||
|
||||
if (appendSlash) {
|
||||
chars[position[0]++] = '/';
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
};
|
||||
root = new FsRoot(fs, rootId, basePath);
|
||||
}
|
||||
|
||||
if (isFakeRoot) {
|
||||
@@ -1037,7 +1016,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
}
|
||||
}
|
||||
else {
|
||||
VirtualFileSystemEntry parentFile = findFileById(parentId, cachedOnly, visited, mask |= id);
|
||||
VirtualFileSystemEntry parentFile = findFileById(parentId, cachedOnly, visited, mask | id);
|
||||
if (parentFile instanceof VirtualDirectoryImpl) {
|
||||
result = ((VirtualDirectoryImpl)parentFile).findChildById(id, cachedOnly);
|
||||
}
|
||||
@@ -1335,11 +1314,12 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
}
|
||||
}
|
||||
|
||||
public static class JarRoot extends VirtualDirectoryImpl {
|
||||
|
||||
private static class JarRoot extends VirtualDirectoryImpl {
|
||||
private final VirtualFile myParentLocalFile;
|
||||
|
||||
private JarRoot(@NotNull NewVirtualFileSystem fs, int rootId, @NotNull VirtualFile parentLocalFile) {
|
||||
super("", null, fs, rootId, 0);
|
||||
super(FS_ROOT_FAKE_NAME, null, fs, rootId, 0);
|
||||
myParentLocalFile = parentLocalFile;
|
||||
}
|
||||
|
||||
@@ -1362,10 +1342,47 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
public void setParent(@NotNull VirtualFile newParent) {
|
||||
throw new IncorrectOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class FsRoot extends VirtualDirectoryImpl {
|
||||
private final String myName;
|
||||
|
||||
private FsRoot(@NotNull NewVirtualFileSystem fs, int rootId, @NotNull String basePath) {
|
||||
super(FS_ROOT_FAKE_NAME, null, fs, rootId, 0);
|
||||
myName = FileUtil.toSystemIndependentName(basePath);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile getParentLocalFile() {
|
||||
return myParentLocalFile;
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char[] appendPathOnFileSystem(int pathLength, int[] position) {
|
||||
String name = getName();
|
||||
int nameLength = name.length();
|
||||
int rootPathLength = pathLength + nameLength;
|
||||
|
||||
// otherwise we called this as a part of longer file path calculation and slash will be added anyway
|
||||
boolean appendSlash = SystemInfo.isWindows && nameLength == 2 && name.charAt(1) == ':' && pathLength == 0;
|
||||
|
||||
if (appendSlash) ++rootPathLength;
|
||||
char[] chars = new char[rootPathLength];
|
||||
|
||||
position[0] = copyString(chars, position[0], name);
|
||||
|
||||
if (appendSlash) {
|
||||
chars[position[0]++] = '/';
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParent(@NotNull VirtualFile newParent) {
|
||||
throw new IncorrectOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -52,6 +52,7 @@ import java.util.List;
|
||||
* User: spLeaner
|
||||
*/
|
||||
public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
private static final int MIN_ICON_HEIGHT = 18;
|
||||
private final InfoAndProgressPanel myInfoAndProgressPanel;
|
||||
private IdeFrame myFrame;
|
||||
|
||||
@@ -176,6 +177,16 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = super.getPreferredSize();
|
||||
if (size == null) return null;
|
||||
|
||||
Insets insets = getInsets();
|
||||
int minHeight = insets.top + insets.bottom + MIN_ICON_HEIGHT;
|
||||
return new Dimension(size.width, Math.max(size.height, minHeight));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWidget(@NotNull final StatusBarWidget widget) {
|
||||
addWidget(widget, Position.RIGHT, "__AUTODETECT__");
|
||||
@@ -839,7 +850,7 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx {
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return new Dimension(24, 18);
|
||||
return new Dimension(24, MIN_ICON_HEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-5
@@ -208,13 +208,15 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(getPreferredWidth(),
|
||||
isVisible() && getParent() != null ? getParent().getSize().height : super.getPreferredSize().height);
|
||||
final Insets insets = getInsets();
|
||||
int width = getFontMetrics(getWidgetFont()).stringWidth(SAMPLE_STRING) + insets.left + insets.right + 2;
|
||||
int height = getFontMetrics(getWidgetFont()).getHeight() + insets.top + insets.bottom + 2;
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
private int getPreferredWidth() {
|
||||
final Insets insets = getInsets();
|
||||
return getFontMetrics(getWidgetFont()).stringWidth(SAMPLE_STRING) + insets.left + insets.right + 2;
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -309,6 +309,7 @@ testng_sm_runner=false
|
||||
show.flex.debug.design.view=false
|
||||
git.new.log=true
|
||||
|
||||
svn.use.terminal=false
|
||||
|
||||
completion.enable.relevant.method.chain.suggestions=false
|
||||
ide.mac.message.sheets.java.emulation=false
|
||||
|
||||
@@ -164,7 +164,6 @@
|
||||
</action>
|
||||
<action id="QuickJavaDoc">
|
||||
<keyboard-shortcut first-keystroke="control Q"/>
|
||||
<keyboard-shortcut first-keystroke="shift F1"/>
|
||||
</action>
|
||||
<action id="ShowBookmarks">
|
||||
<keyboard-shortcut first-keystroke="alt F2"/>
|
||||
|
||||
@@ -972,7 +972,9 @@ public class AllIcons {
|
||||
public static final Icon Bea = IconLoader.getIcon("/providers/bea.png"); // 16x16
|
||||
public static final Icon Cvs = IconLoader.getIcon("/providers/cvs.png"); // 16x16
|
||||
public static final Icon Eclipse = IconLoader.getIcon("/providers/eclipse.png"); // 16x16
|
||||
public static final Icon H2 = IconLoader.getIcon("/providers/h2.png"); // 16x16
|
||||
public static final Icon Hibernate = IconLoader.getIcon("/providers/hibernate.png"); // 16x16
|
||||
public static final Icon Hsqldb = IconLoader.getIcon("/providers/hsqldb.png"); // 16x16
|
||||
public static final Icon Ibm = IconLoader.getIcon("/providers/ibm.png"); // 16x16
|
||||
public static final Icon Microsoft = IconLoader.getIcon("/providers/microsoft.png"); // 16x16
|
||||
public static final Icon Mysql = IconLoader.getIcon("/providers/mysql.png"); // 16x16
|
||||
@@ -980,6 +982,7 @@ public class AllIcons {
|
||||
public static final Icon Postgresql = IconLoader.getIcon("/providers/postgresql.png"); // 16x16
|
||||
public static final Icon Sqlite = IconLoader.getIcon("/providers/sqlite.png"); // 16x16
|
||||
public static final Icon Sun = IconLoader.getIcon("/providers/sun.png"); // 16x16
|
||||
public static final Icon Sybase = IconLoader.getIcon("/providers/sybase.png"); // 16x16
|
||||
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -419,6 +419,9 @@ public class VcsDirectoryConfigurationPanel extends JPanel implements Configurab
|
||||
|
||||
Collection<VcsRootError> myErrors = VcsRootErrorsFinder.getInstance(myProject).find();
|
||||
for (final VcsRootError root : myErrors) {
|
||||
if (!root.getType().equals(VcsRootError.Type.UNREGISTERED_ROOT)) {
|
||||
continue;
|
||||
}
|
||||
final VcsKey vcsKey = root.getVcsKey();
|
||||
final VcsDescriptor vcsDescriptor = myAllVcss.get(vcsKey.getName());
|
||||
String displayVcsName = vcsDescriptor.getDisplayName();
|
||||
|
||||
@@ -9,7 +9,6 @@ import javax.swing.*;
|
||||
* DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
|
||||
*/
|
||||
public class VcsLogIcons {
|
||||
|
||||
private static Icon load(String path) {
|
||||
return IconLoader.getIcon(path, VcsLogIcons.class);
|
||||
}
|
||||
@@ -17,5 +16,4 @@ public class VcsLogIcons {
|
||||
public static final Icon CollapseBranches = load("/icons/CollapseBranches.png"); // 16x16
|
||||
public static final Icon ExpandBranches = load("/icons/ExpandBranches.png"); // 16x16
|
||||
public static final Icon ShowHideLongEdges = load("/icons/ShowHideLongEdges.png"); // 16x16
|
||||
|
||||
}
|
||||
|
||||
+7
-1
@@ -270,13 +270,19 @@ public class BreakpointsDialog extends DialogWrapper {
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
});
|
||||
}).
|
||||
setToolbarPosition(ActionToolbarPosition.TOP).
|
||||
setToolbarBorder(IdeBorderFactory.createEmptyBorder());
|
||||
|
||||
tree.setBorder(IdeBorderFactory.createBorder());
|
||||
|
||||
for (ToggleActionButton action : myToggleRuleActions) {
|
||||
decorator.addExtraAction(action);
|
||||
}
|
||||
|
||||
JPanel decoratedTree = decorator.createPanel();
|
||||
decoratedTree.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
|
||||
myTreeController.setTreeView(tree);
|
||||
|
||||
myTreeController.buildTree(myBreakpointItems);
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.popup.NotLookupOrSearchCondition;
|
||||
import com.intellij.ui.popup.PopupPositionManager;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -79,6 +80,8 @@ public class ShowByteCodeAction extends AnAction {
|
||||
final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(psiElement);
|
||||
if (virtualFile == null) return;
|
||||
|
||||
final RelativePoint bestPopupLocation = JBPopupFactory.getInstance().guessBestPopupLocation(dataContext);
|
||||
|
||||
final SmartPsiElementPointer element = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(psiElement);
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Searching byte code...") {
|
||||
private String myByteCode;
|
||||
@@ -145,7 +148,11 @@ public class ShowByteCodeAction extends AnAction {
|
||||
.createPopup();
|
||||
Disposer.register(popup, component);
|
||||
|
||||
PopupPositionManager.positionPopupInBestPosition(popup, editor, dataContext);
|
||||
if (editor != null) {
|
||||
popup.showInBestPositionFor(editor);
|
||||
} else {
|
||||
popup.show(bestPopupLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.jps.intellilang.instrumentation;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 11/5/13
|
||||
*/
|
||||
public class ErrorPostponingMethodVisitor extends MethodVisitor {
|
||||
|
||||
private final PatternInstrumenter myInstrumenter;
|
||||
private final String myMethodName;
|
||||
|
||||
public ErrorPostponingMethodVisitor(@NotNull PatternInstrumenter instrumenter, String methodName, @Nullable MethodVisitor methodvisitor) {
|
||||
super(Opcodes.ASM4, methodvisitor);
|
||||
myInstrumenter = instrumenter;
|
||||
myMethodName = methodName;
|
||||
}
|
||||
|
||||
public void visitMaxs(int maxStack, int maxLocals) {
|
||||
try {
|
||||
super.visitMaxs(maxStack, maxLocals);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
myInstrumenter.registerError(myMethodName, "visitMaxs", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -183,7 +183,7 @@ class PatternInstrumenter extends ClassVisitor implements Opcodes {
|
||||
if ((access & ACC_STATIC) != 0 && name.equals("<clinit>")) {
|
||||
myHasStaticInitializer = true;
|
||||
|
||||
return new MethodVisitor(Opcodes.ASM4, methodvisitor) {
|
||||
return new ErrorPostponingMethodVisitor(this, name, methodvisitor) {
|
||||
public void visitCode() {
|
||||
super.visitCode();
|
||||
patchStaticInitializer(mv);
|
||||
@@ -206,7 +206,7 @@ class PatternInstrumenter extends ClassVisitor implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
return methodvisitor;
|
||||
return new ErrorPostponingMethodVisitor(this, name, methodvisitor);
|
||||
}
|
||||
|
||||
private static boolean isStringType(Type type) {
|
||||
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.cvsSupport2.cvsoperations.dateOrRevision;
|
||||
|
||||
import org.netbeans.lib.cvsclient.command.Command;
|
||||
import org.netbeans.lib.cvsclient.command.checkout.CheckoutCommand;
|
||||
import org.netbeans.lib.cvsclient.command.checkout.ExportCommand;
|
||||
import org.netbeans.lib.cvsclient.command.update.UpdateCommand;
|
||||
|
||||
/**
|
||||
* author: lesya
|
||||
*/
|
||||
public class CommandWrapper {
|
||||
private final Command myCommand;
|
||||
|
||||
public CommandWrapper(Command command) {
|
||||
myCommand = command;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public void setUpdateByRevisionOrDate(String revision, final String date) {
|
||||
if (isCheckoutCommand()) {
|
||||
asCheckoutCommand().setUpdateByRevisionOrTag(revision);
|
||||
asCheckoutCommand().setUpdateByDate(date);
|
||||
}
|
||||
else if (isUpdateCommand()) {
|
||||
asUpdateCommand().setUpdateByRevisionOrTag(revision);
|
||||
asUpdateCommand().setUpdateByDate(date);
|
||||
}
|
||||
else if (isExportCommand()) {
|
||||
asExportCommand().setUpdateByRevisionOrTag(revision == null && date == null ? "HEAD" : revision);
|
||||
asExportCommand().setUpdateByDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
private UpdateCommand asUpdateCommand() {
|
||||
return ((UpdateCommand)myCommand);
|
||||
}
|
||||
|
||||
private CheckoutCommand asCheckoutCommand() {
|
||||
return ((CheckoutCommand)myCommand);
|
||||
}
|
||||
|
||||
private ExportCommand asExportCommand() {
|
||||
return ((ExportCommand)myCommand);
|
||||
}
|
||||
|
||||
private boolean isUpdateCommand() {
|
||||
return myCommand instanceof UpdateCommand;
|
||||
}
|
||||
|
||||
private boolean isCheckoutCommand() {
|
||||
return myCommand instanceof CheckoutCommand;
|
||||
}
|
||||
|
||||
private boolean isExportCommand() {
|
||||
return myCommand instanceof ExportCommand;
|
||||
}
|
||||
|
||||
}
|
||||
+40
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,20 +19,28 @@ import com.intellij.cvsSupport2.CvsUtil;
|
||||
import com.intellij.cvsSupport2.application.CvsEntriesManager;
|
||||
import com.intellij.cvsSupport2.config.DateOrRevisionSettings;
|
||||
import com.intellij.cvsSupport2.history.CvsRevisionNumber;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.netbeans.lib.cvsclient.admin.Entry;
|
||||
import org.netbeans.lib.cvsclient.command.Command;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* author: lesya
|
||||
* @author lesya
|
||||
*/
|
||||
public class RevisionOrDateImpl implements RevisionOrDate {
|
||||
private String myStickyTag;
|
||||
private String myStickyDate;
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(RevisionOrDateImpl.class);
|
||||
|
||||
@Nullable private String myStickyTag;
|
||||
@Nullable private Date myStickyDate;
|
||||
|
||||
public static RevisionOrDate createOn(@NotNull VirtualFile file) {
|
||||
VirtualFile parent = file.getParent();
|
||||
final VirtualFile parent = file.getParent();
|
||||
return new RevisionOrDateImpl(parent, CvsEntriesManager.getInstance().getEntryFor(parent, file.getName()));
|
||||
}
|
||||
|
||||
@@ -41,27 +49,25 @@ public class RevisionOrDateImpl implements RevisionOrDate {
|
||||
}
|
||||
|
||||
public static RevisionOrDate createOn(VirtualFile parent, Entry entry, DateOrRevisionSettings config) {
|
||||
RevisionOrDateImpl result = new RevisionOrDateImpl(parent, entry);
|
||||
final RevisionOrDateImpl result = new RevisionOrDateImpl(parent, entry);
|
||||
updateOn(result, config);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void updateOn(RevisionOrDateImpl result, DateOrRevisionSettings config) {
|
||||
String stickyTagFromConfig = config.USE_BRANCH ? config.BRANCH : null;
|
||||
String stickyDateFromConfig = config.USE_DATE ? config.getDate() : null;
|
||||
final String stickyTagFromConfig = config.USE_BRANCH ? config.BRANCH : null;
|
||||
final String stickyDateFromConfig = config.USE_DATE ? config.getDate() : null;
|
||||
result.setStickyInfo(stickyTagFromConfig, stickyDateFromConfig);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static RevisionOrDate createOn(DateOrRevisionSettings config) {
|
||||
RevisionOrDateImpl result = new RevisionOrDateImpl();
|
||||
final RevisionOrDateImpl result = new RevisionOrDateImpl();
|
||||
updateOn(result, config);
|
||||
return result;
|
||||
}
|
||||
|
||||
private RevisionOrDateImpl() {
|
||||
|
||||
}
|
||||
private RevisionOrDateImpl() {}
|
||||
|
||||
private RevisionOrDateImpl(VirtualFile parent, Entry entry) {
|
||||
if (entry == null) {
|
||||
@@ -75,7 +81,7 @@ public class RevisionOrDateImpl implements RevisionOrDate {
|
||||
myStickyTag = entry.getStickyTag();
|
||||
}
|
||||
else if (entry.getStickyDateString() != null) {
|
||||
myStickyDate = entry.getStickyDateString();
|
||||
myStickyDate = entry.getStickyDate();
|
||||
}
|
||||
else {
|
||||
lookupDirectory(parent);
|
||||
@@ -91,22 +97,34 @@ public class RevisionOrDateImpl implements RevisionOrDate {
|
||||
}
|
||||
else {
|
||||
myStickyTag = null;
|
||||
myStickyDate = stickyDate;
|
||||
try {
|
||||
myStickyDate = Entry.getLastModifiedDateFormatter().parse(stickyDate);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setForCommand(Command command) {
|
||||
CommandWrapper wrapper = new CommandWrapper(command);
|
||||
wrapper.setUpdateByRevisionOrDate(myStickyTag, myStickyDate);
|
||||
command.setUpdateByRevisionOrDate(myStickyTag, myStickyDate == null ? null : Entry.getLastModifiedDateFormatter().format(myStickyDate));
|
||||
}
|
||||
|
||||
private void lookupDirectory(VirtualFile directory) {
|
||||
String stickyTag = CvsUtil.getStickyTagForDirectory(directory);
|
||||
final String stickyTag = CvsUtil.getStickyTagForDirectory(directory);
|
||||
if (stickyTag != null) {
|
||||
myStickyTag = stickyTag;
|
||||
return;
|
||||
}
|
||||
myStickyDate = CvsUtil.getStickyDateForDirectory(directory);
|
||||
try {
|
||||
final String stickyDateString = CvsUtil.getStickyDateForDirectory(directory);
|
||||
if (stickyDateString != null) {
|
||||
myStickyDate = Entry.STICKY_DATE_FORMAT.parse(stickyDateString);
|
||||
}
|
||||
}
|
||||
catch (ParseException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRevision() {
|
||||
@@ -121,14 +139,15 @@ public class RevisionOrDateImpl implements RevisionOrDate {
|
||||
try {
|
||||
return new CvsRevisionNumber(myStickyTag);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
catch (NumberFormatException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (myStickyDate != null) {
|
||||
return myStickyDate;
|
||||
return Entry.getLastModifiedDateFormatter().format(myStickyDate);
|
||||
} else {
|
||||
return myStickyTag;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,7 +47,7 @@ public class SimpleRevision implements RevisionOrDate {
|
||||
}
|
||||
|
||||
public void setForCommand(Command command) {
|
||||
new CommandWrapper(command).setUpdateByRevisionOrDate(myRevision, null);
|
||||
command.setUpdateByRevisionOrDate(myRevision, null);
|
||||
}
|
||||
|
||||
public CvsRevisionNumber getCvsRevisionNumber() {
|
||||
|
||||
@@ -95,4 +95,8 @@ public abstract class Command {
|
||||
globalOptions.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void setUpdateByRevisionOrDate(String revision, final String date) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -354,4 +354,10 @@ public final class CheckoutCommand extends AbstractCommand implements IUpdatingC
|
||||
}
|
||||
return cvsArguments.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUpdateByRevisionOrDate(String revision, String date) {
|
||||
setUpdateByRevisionOrTag(revision);
|
||||
setUpdateByDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,4 +248,9 @@ public final class ExportCommand extends AbstractCommand {
|
||||
}
|
||||
return cvsArguments.toString();
|
||||
}
|
||||
|
||||
public void setUpdateByRevisionOrDate(String revision, final String date) {
|
||||
setUpdateByRevisionOrTag(revision == null && date == null ? "HEAD" : revision);
|
||||
setUpdateByDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -285,7 +285,7 @@ public final class UpdateCommand extends AbstractCommand
|
||||
}
|
||||
if (getKeywordSubst() != null) {
|
||||
cvsArguments.append("-k");
|
||||
cvsArguments.append(getKeywordSubst().toString());
|
||||
cvsArguments.append(getKeywordSubst());
|
||||
cvsArguments.append(' ');
|
||||
}
|
||||
if (getUpdateByRevision() != null) {
|
||||
@@ -311,4 +311,9 @@ public final class UpdateCommand extends AbstractCommand
|
||||
}
|
||||
return cvsArguments.toString();
|
||||
}
|
||||
|
||||
public void setUpdateByRevisionOrDate(String revision, final String date) {
|
||||
setUpdateByRevisionOrTag(revision);
|
||||
setUpdateByDate(date);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ package org.jetbrains.plugins.gradle;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.SimpleJavaParameters;
|
||||
import com.intellij.externalSystem.JavaProjectData;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemAutoImportAware;
|
||||
@@ -39,14 +37,11 @@ import com.intellij.openapi.externalSystem.service.project.autoimport.CachingExt
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.service.ui.DefaultExternalSystemUiAware;
|
||||
import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.module.EmptyModuleType;
|
||||
import com.intellij.openapi.module.JavaModuleType;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.module.StdModuleTypes;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
|
||||
@@ -55,14 +50,10 @@ import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.PathsList;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import icons.GradleIcons;
|
||||
import org.gradle.tooling.ProjectConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.config.GradleSettingsListenerAdapter;
|
||||
@@ -74,13 +65,11 @@ import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtensi
|
||||
import org.jetbrains.plugins.gradle.service.settings.GradleConfigurable;
|
||||
import org.jetbrains.plugins.gradle.service.task.GradleTaskManager;
|
||||
import org.jetbrains.plugins.gradle.settings.*;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
import org.jetbrains.plugins.gradle.util.GradleUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
@@ -291,9 +280,9 @@ public class GradleManager
|
||||
if (externalProject == null) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+3
-2
@@ -22,6 +22,7 @@ import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData;
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
@@ -127,9 +128,9 @@ public class UseDistributionWithSourcesNotificationProvider extends EditorNotifi
|
||||
if (externalProject == null) {
|
||||
return;
|
||||
}
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new Runnable() {
|
||||
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(module.getProject()) {
|
||||
@Override
|
||||
public void run() {
|
||||
public void execute() {
|
||||
ProjectRootManagerEx.getInstanceEx(module.getProject()).mergeRootsChangesDuring(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
@@ -25,11 +26,13 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.AbstractVcsHelper;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangesUtil;
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -57,6 +60,7 @@ import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.channels.NonWritableChannelException;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -369,30 +373,34 @@ public class SvnUtil {
|
||||
*/
|
||||
@NotNull
|
||||
public static WorkingCopyFormat getFormat(final File path) {
|
||||
int format = 0;
|
||||
WorkingCopyFormat result = null;
|
||||
File dbFile = resolveDatabase(path);
|
||||
|
||||
if (dbFile != null) {
|
||||
SqlJetDb db = null;
|
||||
try {
|
||||
db = SqlJetDb.open(dbFile, false);
|
||||
format = db.getOptions().getUserVersion();
|
||||
}
|
||||
catch (SqlJetException e) {
|
||||
LOG.error(e);
|
||||
} finally {
|
||||
if (db != null) {
|
||||
try {
|
||||
db.close();
|
||||
}
|
||||
catch (SqlJetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
result = FileUtilRt.doIOOperation(new WorkingCopyFormatOperation(dbFile));
|
||||
|
||||
if (result == null) {
|
||||
notifyDatabaseError();
|
||||
}
|
||||
}
|
||||
|
||||
return WorkingCopyFormat.getInstance(format);
|
||||
return result != null ? result : WorkingCopyFormat.UNKNOWN;
|
||||
}
|
||||
|
||||
private static void close(@Nullable SqlJetDb db) {
|
||||
if (db != null) {
|
||||
try {
|
||||
db.close();
|
||||
}
|
||||
catch (SqlJetException e) {
|
||||
notifyDatabaseError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void notifyDatabaseError() {
|
||||
VcsBalloonProblemNotifier.NOTIFICATION_GROUP
|
||||
.createNotification("Some errors occurred while accessing svn working copy database.", NotificationType.ERROR).notify(null);
|
||||
}
|
||||
|
||||
private static File resolveDatabase(final File path) {
|
||||
@@ -803,4 +811,40 @@ public class SvnUtil {
|
||||
// thrown when getting info from repository for non-existent item - like HEAD revision for deleted file
|
||||
SVNErrorCode.ILLEGAL_TARGET.equals(code);
|
||||
}
|
||||
|
||||
private static class WorkingCopyFormatOperation implements FileUtilRt.RepeatableIOOperation<WorkingCopyFormat, RuntimeException> {
|
||||
@NotNull private final File myDbFile;
|
||||
|
||||
public WorkingCopyFormatOperation(@NotNull File dbFile) {
|
||||
myDbFile = dbFile;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WorkingCopyFormat execute(boolean lastAttempt) {
|
||||
// TODO: rewrite it using sqlite jdbc driver
|
||||
SqlJetDb db = null;
|
||||
WorkingCopyFormat result = null;
|
||||
try {
|
||||
// "write" access is requested here for now as workaround - see some details
|
||||
// in https://code.google.com/p/sqljet/issues/detail?id=25 and http://issues.tmatesoft.com/issue/SVNKIT-418.
|
||||
// BUSY error is currently handled same way as others.
|
||||
db = SqlJetDb.open(myDbFile, true);
|
||||
result = WorkingCopyFormat.getInstance(db.getOptions().getUserVersion());
|
||||
}
|
||||
catch (NonWritableChannelException e) {
|
||||
// Such exceptions could be thrown when db is opened in "read" mode, but the db file is readonly (for instance, locked
|
||||
// by other process). See links above for some details.
|
||||
// handle this exception type separately - not to break execution flow
|
||||
LOG.info(e);
|
||||
}
|
||||
catch (SqlJetException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
finally {
|
||||
close(db);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,12 @@ public class Command {
|
||||
myParameters.addAll(parameters);
|
||||
}
|
||||
|
||||
public void putIfNotPresent(@NotNull String parameter) {
|
||||
if (!myParameters.contains(parameter)) {
|
||||
myParameters.add(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public File getConfigDir() {
|
||||
return myConfigDir;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -25,6 +26,8 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -40,9 +43,11 @@ public class CommandExecutor {
|
||||
|
||||
private boolean myIsDestroyed;
|
||||
private boolean myNeedsDestroy;
|
||||
private volatile String myDestroyReason;
|
||||
protected final GeneralCommandLine myCommandLine;
|
||||
private Process myProcess;
|
||||
private OSProcessHandler myHandler;
|
||||
protected Process myProcess;
|
||||
protected OSProcessHandler myHandler;
|
||||
private OutputStreamWriter myProcessWriter;
|
||||
// TODO: Try to implement commands in a way that they manually indicate if they need full output - to prevent situations
|
||||
// TODO: when large amount of data needs to be stored instead of just sequential processing.
|
||||
private CapturingProcessAdapter outputAdapter;
|
||||
@@ -86,16 +91,21 @@ public class CommandExecutor {
|
||||
return myIsDestroyed;
|
||||
}
|
||||
|
||||
public String getDestroyReason() {
|
||||
return myDestroyReason;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
synchronized (myLock) {
|
||||
checkNotStarted();
|
||||
|
||||
try {
|
||||
myProcess = myCommandLine.createProcess();
|
||||
myProcess = createProcess();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(myCommandLine.toString());
|
||||
}
|
||||
myHandler = new OSProcessHandler(myProcess, myCommandLine.getCommandLineString());
|
||||
myHandler = createProcessHandler();
|
||||
myProcessWriter = new OutputStreamWriter(myHandler.getProcessInput());
|
||||
startHandlingStreams();
|
||||
} catch (Throwable t) {
|
||||
listeners().startFailed(t);
|
||||
@@ -104,7 +114,17 @@ public class CommandExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
private void startHandlingStreams() {
|
||||
@NotNull
|
||||
protected OSProcessHandler createProcessHandler() {
|
||||
return new OSProcessHandler(myProcess, myCommandLine.getCommandLineString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Process createProcess() throws ExecutionException {
|
||||
return myCommandLine.createProcess();
|
||||
}
|
||||
|
||||
protected void startHandlingStreams() {
|
||||
outputAdapter = new CapturingProcessAdapter();
|
||||
myHandler.addProcessListener(outputAdapter);
|
||||
myHandler.addProcessListener(new ProcessTracker());
|
||||
@@ -121,6 +141,12 @@ public class CommandExecutor {
|
||||
return outputAdapter.getOutput().getStderr();
|
||||
}
|
||||
|
||||
// TODO: Carefully here - do not modify command from threads other than the one started command execution
|
||||
@NotNull
|
||||
public Command getCommand() {
|
||||
return myCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for process termination
|
||||
* @param timeout
|
||||
@@ -183,6 +209,13 @@ public class CommandExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyProcess(@Nullable String destroyReason) {
|
||||
synchronized (myLock) {
|
||||
myDestroyReason = destroyReason;
|
||||
myNeedsDestroy = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ProcessHandler.destroyProcess() implementations could acquire read lock in its implementation - like OSProcessManager.getInstance().
|
||||
* Some commands are called under write lock - which is generally bad idea, but such logic is not refactored yet.
|
||||
@@ -265,6 +298,23 @@ public class CommandExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
public void write(String value) throws SvnBindException {
|
||||
try {
|
||||
synchronized (myLock) {
|
||||
myProcessWriter.write(value);
|
||||
myProcessWriter.flush();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void logCommand() {
|
||||
LOG.info("Command text " + getCommandText());
|
||||
LOG.info("Command output " + getOutput());
|
||||
}
|
||||
|
||||
private class CommandCancelTracker extends LineCommandAdapter {
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
|
||||
-1
@@ -44,7 +44,6 @@ public class CommandParametersResolutionModule extends BaseCommandRuntimeModule
|
||||
command.setWorkingDirectory(resolveWorkingDirectory(command));
|
||||
}
|
||||
command.setConfigDir(myAuthCallback.getSpecialConfigDir());
|
||||
command.put("--non-interactive");
|
||||
command.saveOriginalParameters();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -85,12 +87,20 @@ public class CommandRuntime {
|
||||
if (exitCode == null || exitCode != 0) {
|
||||
logNullExitCode(executor, exitCode);
|
||||
|
||||
if (executor.isManuallyDestroyed()) {
|
||||
cleanup(executor, command.getWorkingDirectory());
|
||||
|
||||
String destroyReason = executor.getDestroyReason();
|
||||
if (!StringUtil.isEmpty(destroyReason)) {
|
||||
throw new SvnBindException(destroyReason);
|
||||
}
|
||||
}
|
||||
|
||||
if (executor.getErrorOutput().length() > 0) {
|
||||
// handle authentication
|
||||
final String errText = executor.getErrorOutput().trim();
|
||||
final AuthCallbackCase callback = createCallback(errText, command.getRepositoryUrl());
|
||||
final AuthCallbackCase callback = executor instanceof TerminalExecutor ? null : createCallback(errText, command.getRepositoryUrl());
|
||||
if (callback != null) {
|
||||
cleanup(executor, command.getWorkingDirectory());
|
||||
if (callback.getCredentials(errText)) {
|
||||
if (myAuthCallback.getSpecialConfigDir() != null) {
|
||||
command.setConfigDir(myAuthCallback.getSpecialConfigDir());
|
||||
@@ -107,6 +117,9 @@ public class CommandRuntime {
|
||||
// no errors found in error stream => we treat null exitCode as successful, otherwise exception is thrown
|
||||
if (exitCode != null) {
|
||||
// here exitCode != null && exitCode != 0
|
||||
LOG.info("Command - " + executor.getCommandText());
|
||||
LOG.info("Command output - " + executor.getOutput());
|
||||
|
||||
throw new SvnBindException("Svn process exited with error code: " + exitCode);
|
||||
}
|
||||
}
|
||||
@@ -148,7 +161,7 @@ public class CommandRuntime {
|
||||
}
|
||||
|
||||
private void cleanup(@NotNull CommandExecutor executor, @NotNull File workingDirectory) throws SvnBindException {
|
||||
if (executor.isManuallyDestroyed() && executor.getCommandName().isWriteable()) {
|
||||
if (executor.getCommandName().isWriteable()) {
|
||||
File wcRoot = SvnUtil.getWorkingCopyRootNew(workingDirectory);
|
||||
|
||||
// not all commands require cleanup - for instance, some commands operate only with repository - like "svn info <url>"
|
||||
@@ -167,7 +180,19 @@ public class CommandRuntime {
|
||||
|
||||
@NotNull
|
||||
private CommandExecutor newExecutor(@NotNull Command command) {
|
||||
return new CommandExecutor(exePath, command);
|
||||
final CommandExecutor executor;
|
||||
|
||||
if (!Registry.is("svn.use.terminal")) {
|
||||
command.putIfNotPresent("--non-interactive");
|
||||
executor = new CommandExecutor(exePath, command);
|
||||
}
|
||||
else {
|
||||
command.put("--force-interactive");
|
||||
executor = new TerminalExecutor(exePath, command);
|
||||
((TerminalExecutor)executor).addInteractiveListener(new TerminalSshModule(this, executor));
|
||||
}
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public interface InteractiveCommandListener {
|
||||
|
||||
boolean handlePrompt(String line, Key outputType);
|
||||
}
|
||||
+5
@@ -171,6 +171,11 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI {
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
catch (SAXException e) {
|
||||
// status parsing errors are logged separately as sometimes there are parsing errors connected to terminal output handling.
|
||||
// these errors primarily occur when status output is rather large.
|
||||
// and status output could be large, for instance, when working copy is locked (seems that each file is listed in status output).
|
||||
command.logCommand();
|
||||
|
||||
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.CommandLineUtil;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.pty4j.PtyProcess;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class TerminalExecutor extends CommandExecutor {
|
||||
|
||||
// max available value is 480
|
||||
// if greater value is provided than the default value of 80 will be assumed
|
||||
// this could provide unnecessary line breaks and thus could break parsing logic
|
||||
private static final int TERMINAL_WINDOW_MAX_COLUMNS = 480;
|
||||
|
||||
static {
|
||||
if (SystemInfo.isWindows) {
|
||||
System.setProperty("win.pty.cols", String.valueOf(TERMINAL_WINDOW_MAX_COLUMNS));
|
||||
}
|
||||
}
|
||||
|
||||
private final List<InteractiveCommandListener> myInteractiveListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
|
||||
public TerminalExecutor(@NotNull @NonNls String exePath, @NotNull Command command) {
|
||||
super(exePath, command);
|
||||
}
|
||||
|
||||
public void addInteractiveListener(@NotNull InteractiveCommandListener listener) {
|
||||
myInteractiveListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startHandlingStreams() {
|
||||
for (InteractiveCommandListener listener : myInteractiveListeners) {
|
||||
((TerminalProcessHandler)myHandler).addInteractiveListener(listener);
|
||||
}
|
||||
|
||||
super.startHandlingStreams();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected OSProcessHandler createProcessHandler() {
|
||||
return new TerminalProcessHandler(myProcess);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Process createProcess() throws ExecutionException {
|
||||
List<String> parameters =
|
||||
escapeArguments(CommandLineUtil.toCommandLine(myCommandLine.getExePath(), myCommandLine.getParametersList().getList()));
|
||||
|
||||
try {
|
||||
return PtyProcess
|
||||
.exec(ArrayUtil.toStringArray(parameters), myCommandLine.getEnvironment(), myCommandLine.getWorkDirectory().getAbsolutePath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ExecutionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logCommand() {
|
||||
super.logCommand();
|
||||
|
||||
LOG.info("Terminal output " + ((TerminalProcessHandler) myHandler).getTerminalOutput());
|
||||
}
|
||||
|
||||
private static List<String> escapeArguments(List<String> collection) {
|
||||
// TODO: Add additional checks like in java.lang.ProcessImpl constructor
|
||||
return ContainerUtil.map(collection, new Function<String, String>() {
|
||||
@Override
|
||||
public String fun(String s) {
|
||||
return s.contains(" ") ? "\"" + s + "\"" : s;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.execution.process.CapturingProcessAdapter;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class TerminalProcessHandler extends OSProcessHandler {
|
||||
|
||||
// see http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
private static final String NON_CSI_ESCAPE_CODE = "\u001B.[@-_]";
|
||||
private static final String CSI_ESCAPE_CODE = "\u001B\\[(.*?)[@-~]";
|
||||
|
||||
private final List<InteractiveCommandListener> myInteractiveListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
private final CapturingProcessAdapter terminalOutputCapturer = new CapturingProcessAdapter();
|
||||
|
||||
private final StringBuilder outputLine = new StringBuilder();
|
||||
private final StringBuilder errorLine = new StringBuilder();
|
||||
|
||||
public TerminalProcessHandler(@NotNull Process process) {
|
||||
super(process);
|
||||
}
|
||||
|
||||
public void addInteractiveListener(@NotNull InteractiveCommandListener listener) {
|
||||
myInteractiveListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processHasSeparateErrorStream() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void destroyProcessImpl() {
|
||||
final Process process = getProcess();
|
||||
process.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyTextAvailable(String text, Key outputType) {
|
||||
terminalOutputCapturer.onTextAvailable(new ProcessEvent(this, text), outputType);
|
||||
|
||||
// filter terminal escape codes - they are presented in the output for windows platform
|
||||
String filteredText = text.replaceAll(CSI_ESCAPE_CODE, "").replaceAll(NON_CSI_ESCAPE_CODE, "");
|
||||
// trim leading '\r' symbols - as they break xml parsing logic
|
||||
filteredText = StringUtil.trimLeading(filteredText);
|
||||
|
||||
if (!StringUtil.isEmpty(filteredText)) {
|
||||
StringBuilder lastLine = getLastLineFor(outputType);
|
||||
String currentLine = lastLine.append(filteredText).toString();
|
||||
lastLine.setLength(0);
|
||||
|
||||
// check if current line presents some interactive output
|
||||
boolean handled = false;
|
||||
for (InteractiveCommandListener listener : myInteractiveListeners) {
|
||||
handled |= listener.handlePrompt(currentLine, outputType);
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
notify(currentLine, outputType, lastLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notify(@NotNull String text, @NotNull Key outputType, @NotNull StringBuilder lastLine) {
|
||||
// for windows platform output is assumed in format suitable for terminal emulator
|
||||
// for instance, same text could be returned twice with '\r' symbol in between (so in emulator output we'll still see correct
|
||||
// text without duplication)
|
||||
// because of this we manually process '\r' occurrences to get correct output
|
||||
text = removeAllBeforeCaretReturn(text);
|
||||
|
||||
// text is not more than one line - either one line or part of the line
|
||||
if (StringUtil.endsWith(text, "\n")) {
|
||||
// we have full line - notify listeners
|
||||
super.notifyTextAvailable(text, resolveOutputType(text, outputType));
|
||||
}
|
||||
else {
|
||||
// save line part to lastLine
|
||||
lastLine.append(text);
|
||||
}
|
||||
}
|
||||
|
||||
private static String removeAllBeforeCaretReturn(@NotNull String line) {
|
||||
int caretReturn = line.lastIndexOf("\r");
|
||||
|
||||
while (caretReturn >= 0) {
|
||||
if (caretReturn + 1 < line.length() && line.charAt(caretReturn + 1) != '\n') {
|
||||
// next symbol is not '\n' - we should not treat text before found caret return symbol
|
||||
line = line.substring(caretReturn + 1);
|
||||
break;
|
||||
}
|
||||
caretReturn = line.lastIndexOf("\r", caretReturn - 1);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
private static Key resolveOutputType(@NotNull String line, @NotNull Key outputType) {
|
||||
Key result = outputType;
|
||||
|
||||
if (!ProcessOutputTypes.SYSTEM.equals(outputType)) {
|
||||
Matcher errorMatcher = SvnUtil.ERROR_PATTERN.matcher(line);
|
||||
Matcher warningMatcher = SvnUtil.WARNING_PATTERN.matcher(line);
|
||||
|
||||
result = errorMatcher.find() || warningMatcher.find() ? ProcessOutputTypes.STDERR : ProcessOutputTypes.STDOUT;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StringBuilder getLastLineFor(Key outputType) {
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
return errorLine;
|
||||
}
|
||||
else if (ProcessOutputTypes.STDOUT.equals(outputType)) {
|
||||
return outputLine;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown process output type " + outputType);
|
||||
}
|
||||
}
|
||||
|
||||
public String getTerminalOutput() {
|
||||
return terminalOutputCapturer.getOutput().getStdout();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.svn.commandLine;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
import org.jetbrains.idea.svn.dialogs.ServerSSHDialog;
|
||||
import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class TerminalSshModule extends LineCommandAdapter implements CommandRuntimeModule, InteractiveCommandListener {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(TerminalSshModule.class);
|
||||
|
||||
private static final Pattern PASSPHRASE_PROMPT = Pattern.compile("Enter passphrase for key \\'(.*)\\':\\s?");
|
||||
private static final Pattern PASSWORD_PROMPT = Pattern.compile("(.*)\\'s password:\\s?");
|
||||
|
||||
private static final Pattern UNKNOWN_HOST_MESSAGE =
|
||||
Pattern.compile("The authenticity of host \\'((.*) \\((.*)\\))\\' can\\'t be established\\.\\s?");
|
||||
private static final Pattern HOST_FINGERPRINT_MESSAGE = Pattern.compile("(\\w+) key fingerprint is (.*)\\.\\s?");
|
||||
private static final Pattern ACCEPT_HOST_PROMPT = Pattern.compile("Are you sure you want to continue connecting \\(yes/no\\)\\?\\s?");
|
||||
|
||||
@NotNull private final CommandRuntime myRuntime;
|
||||
@NotNull private final CommandExecutor myExecutor;
|
||||
|
||||
private String unknownHost;
|
||||
private String fingerprintAlgorithm;
|
||||
private String hostFingerprint;
|
||||
|
||||
// TODO: Do not accept executor here and make it as command runtime module
|
||||
public TerminalSshModule(@NotNull CommandRuntime runtime, @NotNull CommandExecutor executor) {
|
||||
myExecutor = executor;
|
||||
myRuntime = runtime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NotNull Command command) throws SvnBindException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePrompt(String line, Key outputType) {
|
||||
return checkPassphrase(line) || checkPassword(line) || checkUnknownHost(line);
|
||||
}
|
||||
|
||||
private boolean checkPassphrase(@NotNull String line) {
|
||||
Matcher matcher = PASSPHRASE_PROMPT.matcher(line);
|
||||
|
||||
return matcher.matches() && handleAuthPrompt(SimpleCredentialsDialog.Mode.SSH_PASSPHRASE, matcher.group(1));
|
||||
}
|
||||
|
||||
private boolean checkPassword(@NotNull String line) {
|
||||
Matcher matcher = PASSWORD_PROMPT.matcher(line);
|
||||
|
||||
return matcher.matches() && handleAuthPrompt(SimpleCredentialsDialog.Mode.SSH_PASSWORD, matcher.group(1));
|
||||
}
|
||||
|
||||
private boolean checkUnknownHost(@NotNull String line) {
|
||||
Matcher unknownHostMatcher = UNKNOWN_HOST_MESSAGE.matcher(line);
|
||||
Matcher hostFingerPrintMatcher = HOST_FINGERPRINT_MESSAGE.matcher(line);
|
||||
Matcher acceptHostMatcher = ACCEPT_HOST_PROMPT.matcher(line);
|
||||
|
||||
if (unknownHostMatcher.matches()) {
|
||||
unknownHost = unknownHostMatcher.group(1);
|
||||
}
|
||||
else if (hostFingerPrintMatcher.matches()) {
|
||||
fingerprintAlgorithm = hostFingerPrintMatcher.group(1);
|
||||
hostFingerprint = hostFingerPrintMatcher.group(2);
|
||||
}
|
||||
else if (acceptHostMatcher.matches()) {
|
||||
handleUnknownHost();
|
||||
}
|
||||
|
||||
return unknownHostMatcher.matches() || hostFingerPrintMatcher.matches() || acceptHostMatcher.matches();
|
||||
}
|
||||
|
||||
private void handleUnknownHost() {
|
||||
final Project project = myRuntime.getVcs().getProject();
|
||||
final Ref<Integer> answer = new Ref<Integer>();
|
||||
|
||||
Runnable command = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ServerSSHDialog dialog = new ServerSSHDialog(project, true, unknownHost, fingerprintAlgorithm, hostFingerprint);
|
||||
dialog.show();
|
||||
answer.set(dialog.getResult());
|
||||
}
|
||||
};
|
||||
|
||||
WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(command);
|
||||
|
||||
unknownHost = null;
|
||||
fingerprintAlgorithm = null;
|
||||
hostFingerprint = null;
|
||||
|
||||
sendAnswer(answer.get() == ISVNAuthenticationProvider.REJECTED ? "no" : "yes");
|
||||
}
|
||||
|
||||
private boolean handleAuthPrompt(@NotNull final SimpleCredentialsDialog.Mode mode, @NotNull final String key) {
|
||||
@NotNull final SVNURL repositoryUrl = myExecutor.getCommand().getRepositoryUrl();
|
||||
final Project project = myRuntime.getVcs().getProject();
|
||||
final Ref<String> answer = new Ref<String>();
|
||||
|
||||
Runnable command = new Runnable() {
|
||||
public void run() {
|
||||
SimpleCredentialsDialog dialog = new SimpleCredentialsDialog(project);
|
||||
dialog.setup(mode, repositoryUrl.toDecodedString(), key, true);
|
||||
dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
answer.set(dialog.getPassword());
|
||||
}
|
||||
// TODO: Correctly handle "cancel" - kill the process
|
||||
// TODO: and perform "cleanup" on working copy
|
||||
}
|
||||
};
|
||||
|
||||
WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(command);
|
||||
|
||||
if (!answer.isNull()) {
|
||||
sendAnswer(answer.get());
|
||||
} else {
|
||||
myExecutor.destroyProcess("Authentication canceled for repository: " + repositoryUrl);
|
||||
}
|
||||
|
||||
return !answer.isNull();
|
||||
}
|
||||
|
||||
private boolean sendAnswer(@NotNull String answer) {
|
||||
try {
|
||||
myExecutor.write(answer + "\n");
|
||||
return true;
|
||||
}
|
||||
catch (SvnBindException e) {
|
||||
// TODO: handle this more carefully
|
||||
LOG.info(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.dialogs;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.SvnBundle;
|
||||
@@ -41,12 +42,20 @@ public class ServerSSHDialog extends DialogWrapper {
|
||||
|
||||
public ServerSSHDialog(Project project, boolean store, @NotNull final String host, @Nullable final String algorithm,
|
||||
@NotNull final byte[] fingerprints) {
|
||||
this(project, store, host, algorithm, SVNSSLUtil.getFingerprint(fingerprints, "SHA1"));
|
||||
}
|
||||
|
||||
public ServerSSHDialog(Project project,
|
||||
boolean store,
|
||||
@NotNull final String host,
|
||||
@Nullable final String algorithm,
|
||||
@NotNull String fingerprints) {
|
||||
super(project, true);
|
||||
myStore = store;
|
||||
myHost = host;
|
||||
myAlgorithm = algorithm == null ? "" : algorithm;
|
||||
myAlgorithm = StringUtil.notNullize(algorithm);
|
||||
// todo ?
|
||||
myFingerprints = SVNSSLUtil.getFingerprint(fingerprints, "SHA1");
|
||||
myFingerprints = fingerprints;
|
||||
myResult = ISVNAuthenticationProvider.REJECTED;
|
||||
setOKButtonText(SvnBundle.message("button.text.ssh.accept"));
|
||||
setCancelButtonText(SvnBundle.message("button.text.ssh.reject"));
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.awt.*;
|
||||
public class SimpleCredentialsDialog extends DialogWrapper implements DocumentListener {
|
||||
private boolean myAllowSave;
|
||||
private String myUserName;
|
||||
private Mode myMode;
|
||||
|
||||
private String myRealm;
|
||||
private JTextField myUserNameText;
|
||||
@@ -42,18 +43,24 @@ public class SimpleCredentialsDialog extends DialogWrapper implements DocumentLi
|
||||
|
||||
@NonNls private static final String HELP_ID = "vcs.subversion.authentication";
|
||||
|
||||
protected SimpleCredentialsDialog(Project project) {
|
||||
public SimpleCredentialsDialog(Project project) {
|
||||
super(project, true);
|
||||
setResizable(false);
|
||||
}
|
||||
|
||||
public void setup(String realm, String userName, boolean allowSave) {
|
||||
setup(Mode.DEFAULT, realm, userName, allowSave);
|
||||
}
|
||||
|
||||
public void setup(Mode mode, String realm, String userName, boolean allowSave) {
|
||||
myMode = mode;
|
||||
myRealm = realm;
|
||||
myUserName = userName;
|
||||
myAllowSave = allowSave;
|
||||
getHelpAction().setEnabled(true);
|
||||
init();
|
||||
}
|
||||
|
||||
protected void doHelpAction() {
|
||||
HelpManager.getInstance().invokeHelp(HELP_ID);
|
||||
}
|
||||
@@ -89,7 +96,7 @@ public class SimpleCredentialsDialog extends DialogWrapper implements DocumentLi
|
||||
gb.weightx = 0;
|
||||
gb.fill = GridBagConstraints.NONE;
|
||||
|
||||
label = new JLabel(SvnBundle.message("label.auth.user.name"));
|
||||
label = new JLabel(SvnBundle.message(myMode.equals(Mode.SSH_PASSPHRASE) ? "label.ssh.key.file" : "label.auth.user.name"));
|
||||
panel.add(label, gb);
|
||||
|
||||
// user name field
|
||||
@@ -106,6 +113,7 @@ public class SimpleCredentialsDialog extends DialogWrapper implements DocumentLi
|
||||
}
|
||||
myUserNameText.selectAll();
|
||||
myUserNameText.getDocument().addDocumentListener(this);
|
||||
myUserNameText.setEnabled(myMode.equals(Mode.DEFAULT));
|
||||
|
||||
gb.gridy += 1;
|
||||
gb.weightx = 0;
|
||||
@@ -113,7 +121,7 @@ public class SimpleCredentialsDialog extends DialogWrapper implements DocumentLi
|
||||
gb.fill = GridBagConstraints.NONE;
|
||||
gb.gridwidth = 1;
|
||||
|
||||
label = new JLabel(SvnBundle.message("label.auth.password"));
|
||||
label = new JLabel(SvnBundle.message(myMode.equals(Mode.SSH_PASSPHRASE) ? "label.ssh.passphrase" : "label.auth.password"));
|
||||
panel.add(label, gb);
|
||||
|
||||
// passworde field
|
||||
@@ -152,7 +160,7 @@ public class SimpleCredentialsDialog extends DialogWrapper implements DocumentLi
|
||||
}
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myUserNameText;
|
||||
return myUserNameText.isEnabled() ? myUserNameText : myPasswordText;
|
||||
}
|
||||
|
||||
public boolean shouldCloseOnCross() {
|
||||
@@ -197,4 +205,10 @@ public class SimpleCredentialsDialog extends DialogWrapper implements DocumentLi
|
||||
private void updateOKButton() {
|
||||
getOKAction().setEnabled(isOKActionEnabled());
|
||||
}
|
||||
|
||||
public enum Mode {
|
||||
SSH_PASSPHRASE,
|
||||
SSH_PASSWORD,
|
||||
DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="jna" level="project" />
|
||||
<orderEntry type="library" name="pty4j" level="project" />
|
||||
<orderEntry type="library" name="purejavacomm" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -550,6 +550,7 @@
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.PyDefinitionsAnnotator"/>
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.GeneratorInArgumentListAnnotator"/>
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.StarAnnotator"/>
|
||||
<dumbAnnotator implementation="com.jetbrains.python.validation.StringLiteralQuotesAnnotator"/>
|
||||
|
||||
<customTargetExpressionStubType implementation="com.jetbrains.python.psi.impl.stubs.PropertyStubType"/>
|
||||
<dialectsTokenSetContributor implementation="com.jetbrains.python.PythonTokenSetContributor"/>
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.InsertHandler;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class OverwriteEqualsInsertHandler implements InsertHandler<LookupElement> {
|
||||
public static OverwriteEqualsInsertHandler INSTANCE = new OverwriteEqualsInsertHandler();
|
||||
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
if (context.getCompletionChar() != Lookup.REPLACE_SELECT_CHAR) {
|
||||
return;
|
||||
}
|
||||
Document doc = context.getDocument();
|
||||
int tailOffset = context.getTailOffset();
|
||||
if (doc.getCharsSequence().charAt(tailOffset) == '=') {
|
||||
doc.deleteString(tailOffset, tailOffset+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,12 @@ public class AutoImportQuickFix implements LocalQuickFix, HighPriorityAction {
|
||||
@NotNull
|
||||
public String getText() {
|
||||
if (myUseQualifiedImport) return PyBundle.message("ACT.qualify.with.module");
|
||||
else return PyBundle.message("ACT.NAME.use.import");
|
||||
else if (myImports.size() == 1) {
|
||||
return "Import '" + myImports.get(0).getPresentableText(getNameToImport()) + "'";
|
||||
}
|
||||
else {
|
||||
return PyBundle.message("ACT.NAME.use.import");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -44,12 +44,7 @@ public class FunctionParsing extends Parsing {
|
||||
|
||||
protected void parseFunctionInnards(PsiBuilder.Marker functionMarker) {
|
||||
myBuilder.advanceLexer();
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.IDENTIFIER) {
|
||||
myBuilder.advanceLexer();
|
||||
}
|
||||
else {
|
||||
myBuilder.error(message("PARSE.expected.func.name"));
|
||||
}
|
||||
checkMatchesOrSkip(PyTokenTypes.IDENTIFIER, message("PARSE.expected.func.name"));
|
||||
parseParameterList();
|
||||
parseReturnTypeAnnotation();
|
||||
checkMatches(PyTokenTypes.COLON, message("PARSE.expected.colon"));
|
||||
@@ -85,10 +80,18 @@ public class FunctionParsing extends Parsing {
|
||||
getExpressionParser().parseArgumentList();
|
||||
}
|
||||
else { // empty arglist node, so we always have it
|
||||
myBuilder.mark().done(PyElementTypes.ARGUMENT_LIST);
|
||||
PsiBuilder.Marker argListMarker = myBuilder.mark();
|
||||
argListMarker.setCustomEdgeTokenBinders(LeftBiasedWhitespaceBinder.INSTANCE, null);
|
||||
argListMarker.done(PyElementTypes.ARGUMENT_LIST);
|
||||
}
|
||||
if (atToken(PyTokenTypes.STATEMENT_BREAK)) {
|
||||
decoratorMarker.done(PyElementTypes.DECORATOR_CALL);
|
||||
nextToken();
|
||||
}
|
||||
else {
|
||||
myBuilder.error(message("PARSE.expected.statement.break"));
|
||||
decoratorMarker.done(PyElementTypes.DECORATOR_CALL);
|
||||
}
|
||||
checkMatches(PyTokenTypes.STATEMENT_BREAK, message("PARSE.expected.statement.break"));
|
||||
decoratorMarker.done(PyElementTypes.DECORATOR_CALL);
|
||||
decorated = true;
|
||||
}
|
||||
if (decorated) decoListMarker.done(PyElementTypes.DECORATOR_LIST);
|
||||
@@ -217,7 +220,7 @@ public class FunctionParsing extends Parsing {
|
||||
nextToken();
|
||||
}
|
||||
invalidElements.error(message("PARSE.expected.formal.param.name"));
|
||||
return false;
|
||||
return atToken(endToken) || atToken(PyTokenTypes.COMMA);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.parsing;
|
||||
|
||||
import com.intellij.lang.WhitespacesAndCommentsBinder;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class LeftBiasedWhitespaceBinder implements WhitespacesAndCommentsBinder {
|
||||
public static LeftBiasedWhitespaceBinder INSTANCE = new LeftBiasedWhitespaceBinder();
|
||||
|
||||
@Override
|
||||
public int getEdgePosition(List<IElementType> tokens, boolean atStreamEdge, TokenTextGetter getter) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,17 @@ public class Parsing {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean checkMatchesOrSkip(final IElementType token, final String message) {
|
||||
if (myBuilder.getTokenType() == token) {
|
||||
myBuilder.advanceLexer();
|
||||
return true;
|
||||
}
|
||||
PsiBuilder.Marker mark = myBuilder.mark();
|
||||
myBuilder.advanceLexer();
|
||||
mark.error(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void assertCurrentToken(final PyElementType tokenType) {
|
||||
LOG.assertTrue(myBuilder.getTokenType() == tokenType);
|
||||
}
|
||||
|
||||
@@ -777,7 +777,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
|
||||
public void parseClassDeclaration(PsiBuilder.Marker classMarker, ParsingScope scope) {
|
||||
assertCurrentToken(PyTokenTypes.CLASS_KEYWORD);
|
||||
myBuilder.advanceLexer();
|
||||
checkMatches(PyTokenTypes.IDENTIFIER, IDENTIFIER_EXPECTED);
|
||||
checkMatchesOrSkip(PyTokenTypes.IDENTIFIER, IDENTIFIER_EXPECTED);
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.LPAR) {
|
||||
getExpressionParser().parseArgumentList();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import com.intellij.util.containers.HashSet;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.codeInsight.completion.OverwriteEqualsInsertHandler;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.stdlib.PyNamedTupleType;
|
||||
@@ -888,6 +889,7 @@ public class PyUtil {
|
||||
|
||||
public static LookupElement createNamedParameterLookup(String name) {
|
||||
LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name + "=").withIcon(PlatformIcons.PARAMETER_ICON);
|
||||
lookupElementBuilder = lookupElementBuilder.withInsertHandler(OverwriteEqualsInsertHandler.INSTANCE);
|
||||
return PrioritizedLookupElement.withGrouping(lookupElementBuilder, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.stubs.IStubElementType;
|
||||
@@ -158,12 +159,9 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiElement parent = getParent();
|
||||
if (parent instanceof PyStatementList) {
|
||||
PsiElement pparent = parent.getParent();
|
||||
if (pparent instanceof PyClass) {
|
||||
return (PyClass)pparent;
|
||||
}
|
||||
final PsiElement parent = PsiTreeUtil.getParentOfType(this, StubBasedPsiElement.class);
|
||||
if (parent instanceof PyClass) {
|
||||
return (PyClass)parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.rename.naming.AutomaticRenamer;
|
||||
import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory;
|
||||
import com.intellij.refactoring.rename.naming.NameSuggester;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
@@ -107,5 +108,13 @@ public class PyContainingFileRenamerFactory implements AutomaticRenamerFactory {
|
||||
public boolean isSelectedByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String suggestNameForElement(PsiNamedElement element, NameSuggester suggester, String newClassName, String oldClassName) {
|
||||
if (element instanceof PyFile && element.getName().equals(oldClassName.toLowerCase() + ".py")) {
|
||||
return newClassName.toLowerCase() + ".py";
|
||||
}
|
||||
return super.suggestNameForElement(element, suggester, newClassName, oldClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ public class PyAnnotatingVisitor implements Annotator {
|
||||
BreakContinueAnnotator.class,
|
||||
GlobalAnnotator.class,
|
||||
ImportAnnotator.class,
|
||||
StringLiteralQuotesAnnotator.class,
|
||||
PyBuiltinAnnotator.class,
|
||||
UnsupportedFeatures.class
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.jetbrains.python.psi.PyStringLiteralExpression;
|
||||
import com.jetbrains.python.psi.impl.PyStringLiteralExpressionImpl;
|
||||
@@ -65,7 +66,15 @@ public class StringLiteralQuotesAnnotator extends PyAnnotator {
|
||||
|
||||
private boolean checkTripleQuotedString(ASTNode stringNode, String text, final String quotes) {
|
||||
if (text.length() < 6 || !text.endsWith(quotes)) {
|
||||
getHolder().createErrorAnnotation(stringNode, "Missing closing triple quotes");
|
||||
int startOffset = StringUtil.trimTrailing(stringNode.getText()).lastIndexOf('\n');
|
||||
if (startOffset < 0) {
|
||||
startOffset = stringNode.getTextRange().getStartOffset();
|
||||
}
|
||||
else {
|
||||
startOffset = stringNode.getTextRange().getStartOffset() + startOffset + 1;
|
||||
}
|
||||
TextRange highlightRange = new TextRange(startOffset, stringNode.getTextRange().getEndOffset());
|
||||
getHolder().createErrorAnnotation(highlightRange, "Missing closing triple quotes");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import sys
|
||||
|
||||
var = (sys.platform == 'win32')
|
||||
|
||||
class A():
|
||||
def __init__(self):
|
||||
self.<caret>a = None
|
||||
|
||||
if var:
|
||||
def func(self):
|
||||
self.a = ""
|
||||
else:
|
||||
def func(self):
|
||||
self.a = ()
|
||||
@@ -19,7 +19,7 @@ def f9():
|
||||
|
||||
def deco2(p1, p2): pass
|
||||
|
||||
<warning descr="Parameter 'p2' unfilled">@deco2 # fail: missing p2</warning>
|
||||
<warning descr="Parameter 'p2' unfilled">@deco2</warning> # fail: missing p2
|
||||
def f10():
|
||||
pass
|
||||
|
||||
@@ -61,7 +61,7 @@ class Dec2:
|
||||
def f17():
|
||||
pass
|
||||
|
||||
<warning descr="Parameter 'p2' unfilled">@Dec2 # fail: no p2</warning>
|
||||
<warning descr="Parameter 'p2' unfilled">@Dec2</warning> # fail: no p2
|
||||
def f18():
|
||||
pass
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
@uncallable_deco # some comment
|
||||
def f():
|
||||
pass
|
||||
@@ -0,0 +1,23 @@
|
||||
PyFile:CommentAfterDecorator.py
|
||||
PyFunction('f')
|
||||
PyDecoratorList
|
||||
PyDecorator: @uncallable_deco
|
||||
PsiElement(Py:AT)('@')
|
||||
PyReferenceExpression: uncallable_deco
|
||||
PsiElement(Py:IDENTIFIER)('uncallable_deco')
|
||||
PyArgumentList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiComment(Py:END_OF_LINE_COMMENT)('# some comment')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,2 @@
|
||||
class from:
|
||||
pass
|
||||
@@ -0,0 +1,13 @@
|
||||
PyFile:KeywordAsClassName.py
|
||||
PyClass: null
|
||||
PsiElement(Py:CLASS_KEYWORD)('class')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Identifier expected
|
||||
PsiElement(Py:FROM_KEYWORD)('from')
|
||||
PyArgumentList
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,2 @@
|
||||
def from():
|
||||
pass
|
||||
@@ -0,0 +1,14 @@
|
||||
PyFile:KeywordAsFunctionName.py
|
||||
PyFunction('null')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:function name expected
|
||||
PsiElement(Py:FROM_KEYWORD)('from')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,2 @@
|
||||
def f(from=1, another_one=2):
|
||||
pass
|
||||
@@ -0,0 +1,24 @@
|
||||
PyFile:KeywordAsNamedParameter.py
|
||||
PyFunction('f')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiErrorElement:formal parameter name expected
|
||||
PsiElement(Py:FROM_KEYWORD)('from')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiElement(Py:INTEGER_LITERAL)('1')
|
||||
PsiElement(Py:COMMA)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PyNamedParameter('another_one')
|
||||
PsiElement(Py:IDENTIFIER)('another_one')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('2')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -127,7 +127,7 @@ public class PyEditingTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testEnterInLineComment() { // PY-1739
|
||||
doTestEnter("# foo <caret>bar", "# foo \n# bar");
|
||||
doTestEnter("# foo <caret>bar", "# foo \n# <caret>bar");
|
||||
}
|
||||
|
||||
public void testEnterInPrefixString() { // PY-5058
|
||||
@@ -318,7 +318,8 @@ public class PyEditingTest extends PyTestCase {
|
||||
private void doTestEnter(String before, final String after) {
|
||||
int pos = before.indexOf("<caret>");
|
||||
before = before.replace("<caret>", "");
|
||||
assertEquals(after, doTestTyping(before, pos, '\n'));
|
||||
doTestTyping(before, pos, '\n');
|
||||
myFixture.checkResult(after);
|
||||
}
|
||||
|
||||
private String doTestTyping(final String text, final int offset, final char character) {
|
||||
|
||||
@@ -147,6 +147,11 @@ public class PyFindUsagesTest extends PyTestCase {
|
||||
assertEquals(2, usages.size());
|
||||
}
|
||||
|
||||
public void testConditionalFunctions() { // PY-1448
|
||||
final Collection<UsageInfo> usages = myFixture.testFindUsages("findUsages/ConditionalFunctions.py");
|
||||
assertEquals(3, usages.size());
|
||||
}
|
||||
|
||||
private Collection<UsageInfo> findMultiFileUsages(String filename) {
|
||||
final String testName = getTestName(false);
|
||||
myFixture.copyDirectoryToProject("findUsages/" + testName, "");
|
||||
|
||||
@@ -33,20 +33,20 @@ import org.jetbrains.annotations.NonNls;
|
||||
public class PyQuickFixTest extends PyTestCase {
|
||||
|
||||
public void testAddImport() {
|
||||
doInspectionTest(new String[] { "AddImport.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.NAME.use.import"), true, true);
|
||||
doInspectionTest(new String[] { "AddImport.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
|
||||
}
|
||||
|
||||
public void testAddImportDoc() {
|
||||
doInspectionTest(new String[] { "AddImportDoc.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.NAME.use.import"), true, true);
|
||||
doInspectionTest(new String[] { "AddImportDoc.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
|
||||
}
|
||||
|
||||
public void testAddImportDocComment() { // PY-728
|
||||
doInspectionTest(new String[] { "AddImportDocComment.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.NAME.use.import"), true, true);
|
||||
doInspectionTest(new String[] { "AddImportDocComment.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
|
||||
}
|
||||
|
||||
public void testImportFromModule() {
|
||||
doInspectionTest(new String[] { "importFromModule/foo/bar.py", "importFromModule/foo/baz.py", "importFromModule/foo/__init__.py" },
|
||||
PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.NAME.use.import"), true, true);
|
||||
PyUnresolvedReferencesInspection.class, "Import 'importFromModule.foo.baz'", true, true);
|
||||
}
|
||||
|
||||
public void testImportFromModuleStar() { // PY-6302
|
||||
@@ -54,7 +54,7 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
myFixture.copyDirectoryToProject("importFromModuleStar", "");
|
||||
myFixture.configureFromTempProjectFile("source.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("ACT.NAME.use.import"));
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention("Import 'target.xyzzy()'");
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile("importFromModuleStar/source_after.py");
|
||||
@@ -80,7 +80,7 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
boolean oldHighlightUnused = settings.HIGHLIGHT_UNUSED_IMPORTS;
|
||||
settings.HIGHLIGHT_UNUSED_IMPORTS = false;
|
||||
try {
|
||||
doInspectionTest(new String[]{"AddToImportFromList.py", "AddToImportFromFoo.py"}, PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.NAME.use.import"), true, true);
|
||||
doInspectionTest(new String[]{"AddToImportFromList.py", "AddToImportFromFoo.py"}, PyUnresolvedReferencesInspection.class, "Import 'foo(a) from AddToImportFromFoo'", true, true);
|
||||
}
|
||||
finally {
|
||||
settings.HIGHLIGHT_UNUSED_IMPORTS = oldHighlightUnused;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.jetbrains.python.documentation.DocStringFormat;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
@@ -583,4 +584,21 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
"f('foo').<caret>\n");
|
||||
assertTrue(results.contains("lower"));
|
||||
}
|
||||
|
||||
public void testOverwriteEqualsSign() { // PY-1337
|
||||
doTestByText("def foo(school=None, kiga=None): pass\n" +
|
||||
"foo(<caret>school=None)");
|
||||
myFixture.type("sch");
|
||||
myFixture.finishLookup(Lookup.REPLACE_SELECT_CHAR);
|
||||
myFixture.checkResult("def foo(school=None, kiga=None): pass\n" +
|
||||
"foo(school=None)");
|
||||
}
|
||||
|
||||
public void testOverwriteBracket() { // PY-6095
|
||||
doTestByText("bar = {'a': '1'}\n" +
|
||||
"print ba<caret>['a']");
|
||||
myFixture.finishLookup(Lookup.REPLACE_SELECT_CHAR);
|
||||
myFixture.checkResult("bar = {'a': '1'}\n" +
|
||||
"print bar<caret>['a']");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,6 +402,22 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCommentAfterDecorator() { // PY-5912
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testKeywordAsNamedParameter() { // PY-8318
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testKeywordAsClassName() { // PY-8319
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testKeywordAsFunctionName() { // PY-8319
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void doTest(LanguageLevel languageLevel) {
|
||||
LanguageLevel prev = myLanguageLevel;
|
||||
myLanguageLevel = languageLevel;
|
||||
|
||||
Reference in New Issue
Block a user