Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2013-11-06 12:24:37 +01:00
99 changed files with 1275 additions and 1477 deletions
@@ -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;
}
}
@@ -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;
}
}
}
@@ -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);
}
});
@@ -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;
}
}
@@ -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();
}
}
}
@@ -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() {
@@ -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() {
@@ -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() {
@@ -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 {
@@ -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,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()) {
@@ -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
@@ -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();
@@ -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()) {
@@ -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);
@@ -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() {
@@ -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() {
@@ -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();
@@ -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));
}
}
@@ -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) {
@@ -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);
}
@@ -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;
}
@@ -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: *
@@ -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));
@@ -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();
}
}
}
@@ -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
@@ -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
}
@@ -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
}
@@ -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);
}
}
}
});
@@ -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);
}
}
}
@@ -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) {
@@ -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;
}
}
@@ -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;
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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() {
@@ -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) {
@@ -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
@@ -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);
}
@@ -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
}
}
+3
View File
@@ -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>
+1
View File
@@ -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"/>
@@ -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;