Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2018-01-31 21:47:54 +01:00
29 changed files with 450 additions and 420 deletions
@@ -57,6 +57,7 @@ public class CaptureStorage {
return;
}
try {
//noinspection SuspiciousMethodCalls
CapturedStack stack = STORAGE.get(new HardKey(key));
Deque<InsertMatch> currentStacks = CURRENT_STACKS.get();
if (stack != null) {
@@ -131,6 +132,7 @@ public class CaptureStorage {
private final CapturedStack myValue;
public WeakKey(Object key, CapturedStack value, ReferenceQueue q) {
//noinspection unchecked
super(key, q);
myHash = System.identityHashCode(key);
myValue = value;
@@ -247,6 +249,7 @@ public class CaptureStorage {
// to be run from the debugger
@SuppressWarnings("unused")
public static Object[][] getRelatedStack(Object key, int limit) {
//noinspection SuspiciousMethodCalls
CapturedStack stack = STORAGE.get(new HardKey(key));
if (stack == null) {
return null;
@@ -18,6 +18,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiFile;
import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.XSourcePosition;
@@ -151,7 +152,8 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator implements XDebugg
}
Pair<PsiElement, TextRange> pair = findExpression(elementAtCursor, sideEffectsAllowed);
if (pair != null) {
return new ExpressionInfo(pair.getSecond(), null, null, pair.getFirst());
PsiElement element = pair.getFirst();
return new ExpressionInfo(pair.getSecond(), null, null, element instanceof PsiExpression ? element : null);
}
} catch (IndexNotReadyException ignored) {}
return null;
@@ -0,0 +1,13 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.lang.jvm.actions
interface ActionRequest {
/**
* Request may be bound to the PSI-element in call-site language,
* which means request will become invalid if element is invalidated.
*
* @return `true` if it is safe to call other methods of this request, `false` otherwise
*/
val isValid: Boolean
}
@@ -1,12 +1,10 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.lang.jvm.actions
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.types.JvmSubstitutor
interface CreateExecutableRequest {
val isValid: Boolean
interface CreateExecutableRequest : ActionRequest {
val modifiers: Collection<JvmModifier>
@@ -1,32 +1,10 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.lang.jvm.actions
import com.intellij.lang.jvm.JvmModifier
import com.intellij.lang.jvm.types.JvmSubstitutor
interface CreateFieldRequest {
/**
* Request may be bound to the PSI-element in call-site language,
* which means request will become invalid if element is invalidated.
*
* @return `true` if it is safe to call other methods of this object, `false` otherwise
*/
val isValid: Boolean
interface CreateFieldRequest : ActionRequest {
/**
* @return name of the field to be created
@@ -16,6 +16,7 @@
package com.intellij.java.propertyBased;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.util.PsiTreeUtil;
@@ -23,6 +24,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.testFramework.propertyBased.CompletionPolicy;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
@@ -30,6 +32,18 @@ import java.util.Arrays;
* @author peter
*/
class JavaCompletionPolicy extends CompletionPolicy {
@Nullable
@Override
protected String getExpectedVariant(@NotNull Editor editor, @NotNull PsiFile file, @NotNull PsiElement leaf, @Nullable PsiReference ref) {
if (isBuggyInjection(file)) return null;
return super.getExpectedVariant(editor, file, leaf, ref);
}
// a language where there are bugs in completion which maintainers of this Java-specific tests can't or don't want to fix
private static boolean isBuggyInjection(@NotNull PsiFile file) {
return Arrays.asList("XML", "HTML").contains(file.getLanguage().getID());
}
@Override
protected boolean isAfterError(@NotNull PsiFile file, @NotNull PsiElement leaf) {
@@ -184,6 +184,7 @@ abstract class LineStatusTrackerBase<R : Range> {
}
override fun onUnfreeze(side: Side) {
calcInnerRanges()
installMissingHighlighters()
}
@@ -194,7 +195,8 @@ abstract class LineStatusTrackerBase<R : Range> {
}
private fun calcInnerRanges() {
if (isDetectWhitespaceChangedLines()) {
if (isDetectWhitespaceChangedLines() &&
!documentTracker.isFrozen()) {
for (block in blocks) {
if (block.ourData.innerRanges == null) {
block.ourData.innerRanges = calcInnerRanges(block)
@@ -32,19 +32,12 @@
<columns value="6"/>
</properties>
</component>
<scrollpane id="80db7" class="com.intellij.ui.components.JBScrollPane">
<component id="87e" class="com.intellij.ui.EditorTextField" binding="myDescriptionArea" custom-create="true">
<constraints>
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="87e" class="com.intellij.ui.EditorTextField" binding="myDescriptionArea" custom-create="true">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
</component>
<component id="d6e35" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="2" use-parent-layout="false"/>
@@ -53,19 +46,12 @@
<text value="Description:"/>
</properties>
</component>
<scrollpane id="c034f" class="com.intellij.ui.components.JBScrollPane">
<component id="e20d2" class="com.intellij.ui.EditorTextField" binding="myChangeNotesArea" custom-create="true">
<constraints>
<grid row="2" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="e20d2" class="com.intellij.ui.EditorTextField" binding="myChangeNotesArea" custom-create="true">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
</component>
<component id="795b5" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="2" use-parent-layout="false"/>
@@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsUtil;
@@ -40,6 +41,7 @@ import com.intellij.openapi.options.FontSize;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.DimensionService;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.InvalidDataException;
@@ -63,6 +65,7 @@ import com.intellij.ui.popup.PopupPositionManager;
import com.intellij.util.Url;
import com.intellij.util.Urls;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.accessibility.ScreenReader;
@@ -102,6 +105,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
@NonNls private static final String DOCUMENTATION_TOPIC_ID = "reference.toolWindows.Documentation";
private static final int PREFERRED_HEIGHT_MAX_EM = 10;
private static final JBDimension MAX_DEFAULT = new JBDimension(650, 500);
private static final JBDimension MIN_DEFAULT = new JBDimension(300, 59);
private final ExternalDocAction myExternalDocAction;
private DocumentationManager myManager;
@@ -485,7 +490,8 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
if (myHint == null && myManager.myToolWindow == null) {
int em = myEditorPane.getFont().getSize();
int prefHeightMax = PREFERRED_HEIGHT_MAX_EM * em;
return new Dimension(size.width, Math.min(prefHeightMax, size.height));
return new Dimension(size.width, Math.min(prefHeightMax,
size.height + (needsToolbar() ? myControlPanel.getPreferredSize().height : 0)));
}
return size;
}
@@ -781,56 +787,104 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
}
private void showHint() {
LookupEx lookup = LookupManager.getActiveLookup(myManager.getEditor());
int maxWidth = JBUI.scale(lookup != null ? 435 : 650);
Editor editor = myManager.getEditor();
LookupEx lookup = LookupManager.getActiveLookup(editor);
int maxWidth = lookup != null ? JBUI.scale(435) : MAX_DEFAULT.width;
boolean lookupActive = lookup != null && lookup.getCurrentItem() != null && lookup.getComponent().isShowing();
if (myHint != null && myHint.getDimensionServiceKey() == null) {
Dimension preferredSize = myEditorPane.getPreferredSize();
int width = definitionPreferredWidth();
width = width < 0 ? preferredSize.width : width;
myResizing = true;
int height = preferredSize.height + (needsToolbar() ? myControlPanel.getPreferredSize().height : 0);
Dimension hintSize = new Dimension(Math.min(maxWidth, Math.max(JBUI.scale(300), width)),
Math.min(JBUI.scale(500), Math.max(JBUI.scale(59), height)));
if (lookupActive && myHint.getLocationOnScreen().x < lookup.getComponent().getLocationOnScreen().x) {
myHint.setLocation(new RelativePoint(lookup.getComponent(), new Point(-hintSize.width - 5, 0)));
if (myHint != null) {
Dimension hintSize;
if (myHint.getDimensionServiceKey() == null) {
Dimension preferredSize = myEditorPane.getPreferredSize();
int width = definitionPreferredWidth();
width = width < 0 ? preferredSize.width : width;
myResizing = true;
int height = preferredSize.height + (needsToolbar() ? myControlPanel.getPreferredSize().height : 0);
hintSize = new Dimension(Math.min(maxWidth, Math.max(JBUI.scale(300), width)),
Math.min(MAX_DEFAULT.height, Math.max(MIN_DEFAULT.height, height)));
} else {
hintSize = DimensionService.getInstance().getSize(DocumentationManager.NEW_JAVADOC_LOCATION_AND_SIZE, myManager.myProject);
hintSize = hintSize != null ? hintSize : MIN_DEFAULT;
}
Point location = myHint.getLocationOnScreen();
if (lookupActive && location.x < lookup.getComponent().getLocationOnScreen().x) {
// pin upper right corner (instead of default upper left)
location = new RelativePoint(lookup.getComponent(), new Point(-hintSize.width - 5, 0)).getScreenPoint();
myHint.setLocation(location);
} else if (editor != null && editor.getComponent().isShowing()) {
// pin lower bound (instead of default upper)
Point preferredLocation = JBPopupFactory.getInstance().guessBestPopupLocation(editor).getScreenPoint();
preferredLocation.y -= editor.getLineHeight();
if (location.y < preferredLocation.y) {
location = new Point(location.x, preferredLocation.y - hintSize.height);
myHint.setLocation(location);
}
}
if (myIsShown) {
Rectangle screen = ScreenUtil.getScreenRectangle(myEditorPane);
int xOverdraft = location.x + hintSize.width - screen.x - screen.width;
if (xOverdraft > 0) {
myHint.setLocation(new Point(location.x - xOverdraft, location.y));
}
int yUnderDraft = screen.y - location.y;
if (yUnderDraft > 0) {
location.y += yUnderDraft;
hintSize.height -= yUnderDraft;
}
int yOverdraft = location.y + hintSize.height - screen.y - screen.height;
if (yOverdraft > 0) {
hintSize.height -= yOverdraft;
}
}
myHint.setSize(hintSize);
}
if (!myIsShown && myHint != null && !ApplicationManager.getApplication().isUnitTestMode()) {
myResizing = true;
Component focusOwner = IdeFocusManager.getInstance(myManager.myProject).getFocusOwner();
DataContext dataContext = DataManager.getInstance().getDataContext(focusOwner);
if (lookupActive) {
Component lookupComponent = lookup.getComponent();
Point lookupPosition = lookupComponent.getLocationOnScreen();
Rectangle screenRectangle = ScreenUtil.getScreenRectangle(lookupComponent);
int lookupWidthAndGap = lookupComponent.getWidth() + 5;
int x = lookupPosition.x + lookupWidthAndGap;
Dimension hintSize = myHint.getSize();
RelativePoint point;
if (x + Math.max(hintSize.width, maxWidth) > screenRectangle.width) {
point = new RelativePoint(lookupComponent, new Point(-hintSize.width - 5, 0));
} else {
point = new RelativePoint(lookupComponent, new Point(lookupWidthAndGap, 0));
}
myHint.show(point);
lookup.addLookupListener(new LookupAdapter() {
@Override
public void lookupCanceled(LookupEvent event) {
final AbstractPopup hint = myHint;
if (hint != null && hint.canClose() && hint.isVisible()) {
hint.cancel();
}
if (!myIsShown && !ApplicationManager.getApplication().isUnitTestMode()) {
myResizing = true;
Component focusOwner = IdeFocusManager.getInstance(myManager.myProject).getFocusOwner();
DataContext dataContext = DataManager.getInstance().getDataContext(focusOwner);
if (lookupActive) {
Component lookupComponent = lookup.getComponent();
Point lookupPosition = lookupComponent.getLocationOnScreen();
Rectangle screenRectangle = ScreenUtil.getScreenRectangle(lookupComponent);
int lookupWidthAndGap = lookupComponent.getWidth() + 5;
int x = lookupPosition.x + lookupWidthAndGap;
RelativePoint point;
// if documentation doesn't fit into screen, put it on the left hand side
if (x + Math.max(hintSize.width, maxWidth) > screenRectangle.width) {
point = new RelativePoint(lookupComponent, new Point(-hintSize.width - 5, 0));
} else {
point = new RelativePoint(lookupComponent, new Point(lookupWidthAndGap, 0));
}
});
} else {
PopupPositionManager.positionPopupInBestPosition(myHint, myManager.getEditor(), dataContext);
}
myIsShown = true;
if (myHint.getDimensionServiceKey() == null) {
SwingUtilities.invokeLater(() -> registerSizeTracker());
myHint.show(point);
lookup.addLookupListener(new LookupAdapter() {
@Override
public void lookupCanceled(LookupEvent event) {
final AbstractPopup hint = myHint;
if (hint != null && hint.canClose() && hint.isVisible()) {
hint.cancel();
}
}
});
} else if (editor != null && editor.getComponent().isShowing()) {
// let's try to fit at least of half of maximum size on the bottom
Point preferredLocation = JBPopupFactory.getInstance().guessBestPopupLocation(editor).getScreenPoint();
Rectangle preferred = new Rectangle(preferredLocation.x, preferredLocation.y, MAX_DEFAULT.width, MAX_DEFAULT.height / 2);
Rectangle adjusted = (Rectangle)preferred.clone();
ScreenUtil.fitToScreen(adjusted);
// if we fail, show documentation on top
if (preferred.y != adjusted.y) {
preferredLocation.y -= editor.getLineHeight() + hintSize.height;
}
myHint.show(new RelativePoint(preferredLocation));
}
else {
PopupPositionManager.positionPopupInBestPosition(myHint, editor, dataContext);
}
myIsShown = true;
if (myHint.getDimensionServiceKey() == null) {
SwingUtilities.invokeLater(() -> registerSizeTracker());
}
}
}
}
@@ -1075,7 +1129,7 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
}
private boolean needsToolbar() {
return myHint != null && Registry.is("documentation.show.toolbar");
return myManager.myToolWindow == null && Registry.is("documentation.show.toolbar");
}
private static class MyGearActionGroup extends DefaultActionGroup implements HintManagerImpl.ActionToIgnore {
@@ -1,6 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.find.actions;
import com.intellij.codeInsight.TargetElementUtil;
@@ -1006,25 +1004,17 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
myWidth = newWidth;
int rowsToShow = Math.min(30, data.size());
Dimension dimension = new Dimension(newWidth, table.getRowHeight() * rowsToShow);
Rectangle rectangle = fitToScreen(dimension, popupPosition, table);
if (!data.isEmpty()) {
ScrollingUtil.ensureSelectionExists(table);
}
table.setSize(rectangle.getSize());
//table.setPreferredSize(dimension);
//table.setMaximumSize(dimension);
//table.setPreferredScrollableViewportSize(dimension);
Dimension footerSize = ((AbstractPopup)popup).getFooterPreferredSize();
int footer = footerSize.height;
int footerBorder = footer == 0 ? 0 : 1;
Insets insets = ((AbstractPopup)popup).getPopupBorder().getBorderInsets(content);
rectangle.height += headerSize.height + footer + footerBorder + insets.top + insets.bottom;
ScreenUtil.fitToScreen(rectangle);
int minHeight = headerSize.height + footer + footerBorder + insets.top + insets.bottom;
Rectangle rectangle = getPreferredBounds(table, popupPosition.getScreenPoint(), newWidth, minHeight, data.size());
table.setSize(rectangle.width, rectangle.height - minHeight);
if (!data.isEmpty()) ScrollingUtil.ensureSelectionExists(table);
Dimension newDim = rectangle.getSize();
window.setBounds(rectangle);
window.setMinimumSize(newDim);
@@ -1034,16 +1024,19 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
window.repaint();
}
private static Rectangle fitToScreen(@NotNull Dimension newDim, @NotNull RelativePoint popupPosition, JTable table) {
Rectangle rectangle = new Rectangle(popupPosition.getScreenPoint(), newDim);
ScreenUtil.fitToScreen(rectangle);
if (rectangle.getHeight() != newDim.getHeight()) {
int newHeight = (int)rectangle.getHeight();
int roundedHeight = newHeight - newHeight % table.getRowHeight();
rectangle.setSize((int)rectangle.getWidth(), Math.max(roundedHeight, table.getRowHeight()));
private static Rectangle getPreferredBounds(@NotNull JTable table, @NotNull Point point, int width, int minHeight, int modelRows) {
boolean addExtraSpace = Registry.is("ide.preferred.scrollable.viewport.extra.space");
int visibleRows = Math.min(30, modelRows);
int rowHeight = table.getRowHeight();
int space = addExtraSpace && visibleRows < modelRows ? rowHeight / 2 : 0;
int height = visibleRows * rowHeight + minHeight + space;
Rectangle bounds = new Rectangle(point.x, point.y, width, height);
ScreenUtil.fitToScreen(bounds);
if (bounds.height != height) {
minHeight += addExtraSpace && space == 0 ? rowHeight / 2 : space;
bounds.height = Math.max(1, (bounds.height - minHeight) / rowHeight) * rowHeight + minHeight;
}
return rectangle;
return bounds;
}
private void appendMoreUsages(Editor editor,
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2015 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.util;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
@@ -623,9 +609,6 @@ public class FileStructurePopup implements Disposable, TreeActionsOwner {
panel.add(topPanel, BorderLayout.NORTH);
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTree);
scrollPane.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP | SideBorder.BOTTOM));
Dimension preferredSize = scrollPane.getPreferredSize();
preferredSize.width = Math.max(chkPanel.getPreferredSize().width, JBUI.scale(350));
scrollPane.setPreferredSize(preferredSize);
panel.add(scrollPane, BorderLayout.CENTER);
//panel.add(createSouthPanel(), BorderLayout.SOUTH);
DataManager.registerDataProvider(panel, new DataProvider() {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.util.gotoByName;
import com.intellij.featureStatistics.FeatureUsageTracker;
@@ -148,10 +134,6 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
bounds.y += layeredPane.getHeight();
final Dimension preferredScrollPaneSize = myListScrollPane.getPreferredSize();
int lastVisibleRow = Math.min(myList.getVisibleRowCount(), myList.getModel().getSize()) - 1;
Rectangle visibleBounds = lastVisibleRow < 0 ? null : myList.getCellBounds(0, lastVisibleRow);
preferredScrollPaneSize.height = visibleBounds != null ? visibleBounds.height : UIManager.getFont("Label.font").getSize();
preferredScrollPaneSize.width = Math.max(myTextFieldPanel.getWidth(), preferredScrollPaneSize.width);
// in 'focus follows mouse' mode, to avoid focus escaping to editor, don't reduce popup size when list size is reduced
@@ -31,6 +31,12 @@ import javax.swing.*;
* @see SearchableOptionContributor
*/
public interface SearchableConfigurable extends Configurable {
/**
* Unique configurable id.
* Note this id should be THE SAME as the one specified in XML.
* @see ConfigurableEP#id
*/
@NotNull
@NonNls
String getId();
@@ -1,6 +1,4 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.ui;
import com.intellij.CommonBundle;
@@ -499,13 +497,6 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
private void createUIComponents() {
myTree = new Tree() {
@Override
public Dimension getPreferredScrollableViewportSize() {
Dimension size = super.getPreferredScrollableViewportSize();
size = new Dimension(size.width + 20, size.height);
return size;
}
@Override
@SuppressWarnings("NonStaticInitializer")
public JToolTip createToolTip() {
@@ -381,52 +381,4 @@ public class JBList<E> extends JList<E> implements ComponentWithEmptyText, Compo
}
}
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredScrollableViewportSize(this);
}
@NotNull
static Dimension getPreferredScrollableViewportSize(@NotNull JList list) {
Dimension size = list.getPreferredSize();
if (size == null) return new Dimension();
if (JList.VERTICAL != list.getLayoutOrientation()) return size;
int fixedWidth = list.getFixedCellWidth();
int fixedHeight = list.getFixedCellHeight();
ListModel model = list.getModel();
int modelRows = model == null ? 0 : model.getSize();
if (modelRows <= 0) {
if (fixedWidth <= 0) fixedWidth = Registry.intValue("ide.preferred.scrollable.viewport.fixed.width");
if (fixedWidth <= 0) fixedWidth = JBUI.scale(256); // scaled value from JDK
if (fixedHeight <= 0) fixedHeight = Registry.intValue("ide.preferred.scrollable.viewport.fixed.height");
if (fixedHeight <= 0) fixedHeight = JBUI.scale(16); // scaled value from JDK
}
int visibleRows = list.getVisibleRowCount();
if (visibleRows <= 0) visibleRows = Registry.intValue("ide.preferred.scrollable.viewport.visible.rows");
boolean addExtraSpace = 0 < visibleRows && visibleRows < modelRows && Registry.is("ide.preferred.scrollable.viewport.extra.space");
Insets insets = list.getInsets();
size.height = insets != null ? insets.top + insets.bottom : 0;
if (0 < fixedWidth && 0 < fixedHeight) {
size.width = insets != null ? insets.left + insets.right + fixedWidth : fixedWidth;
size.height += fixedHeight * visibleRows;
if (addExtraSpace) size.height += fixedHeight / 2;
}
else if (addExtraSpace) {
Rectangle bounds = list.getCellBounds(visibleRows, visibleRows);
if (bounds != null) size.height = bounds.y + bounds.height / 2;
}
else if (visibleRows > 0) {
int lastRow = Math.min(visibleRows, modelRows) - 1;
Rectangle bounds = list.getCellBounds(lastRow, lastRow);
if (bounds != null) {
size.height = bounds.y + bounds.height;
if (insets != null) size.height += insets.bottom;
}
}
return size;
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2016 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.components;
import com.intellij.openapi.diagnostic.Logger;
@@ -676,116 +662,58 @@ public class JBScrollPane extends JScrollPane {
@Override
public Dimension preferredLayoutSize(Container parent) {
/* Sync the (now obsolete) policy fields with the
* JScrollPane.
*/
JScrollPane scrollPane = (JScrollPane)parent;
vsbPolicy = scrollPane.getVerticalScrollBarPolicy();
hsbPolicy = scrollPane.getHorizontalScrollBarPolicy();
Dimension result = new Dimension();
Insets insets = parent.getInsets();
int prefWidth = insets.left + insets.right;
int prefHeight = insets.top + insets.bottom;
JScrollPane pane = (JScrollPane)parent;
JBInsets.addTo(result, pane.getInsets());
/* Note that viewport.getViewSize() is equivalent to
* viewport.getView().getPreferredSize() modulo a null
* view or a view whose size was explicitly set.
*/
Dimension extentSize = null;
Dimension viewSize = null;
Component view = null;
Border border = pane.getViewportBorder();
if (border != null) JBInsets.addTo(result, border.getBorderInsets(parent));
int vsbPolicy = pane.getVerticalScrollBarPolicy();
int hsbPolicy = pane.getHorizontalScrollBarPolicy();
if (viewport != null) {
extentSize = viewport.getPreferredSize();
view = viewport.getView();
Component view = viewport.getView();
if (view != null) {
viewSize = view.getPreferredSize();
} else {
viewSize = new Dimension(0, 0);
}
}
/* If there's a viewport add its preferredSize.
*/
if (extentSize != null) {
prefWidth += extentSize.width;
prefHeight += extentSize.height;
}
/* If there's a JScrollPane.viewportBorder, add its insets.
*/
Border viewportBorder = scrollPane.getViewportBorder();
if (viewportBorder != null) {
Insets vpbInsets = viewportBorder.getBorderInsets(parent);
prefWidth += vpbInsets.left + vpbInsets.right;
prefHeight += vpbInsets.top + vpbInsets.bottom;
}
/* If a header exists and it's visible, factor its
* preferred size in.
*/
if ((rowHead != null) && rowHead.isVisible()) {
prefWidth += rowHead.getPreferredSize().width;
}
if ((colHead != null) && colHead.isVisible()) {
prefHeight += colHead.getPreferredSize().height;
}
/* If a scrollbar is going to appear, factor its preferred size in.
* If the scrollbars policy is AS_NEEDED, this can be a little
* tricky:
*
* - If the view is a Scrollable then scrollableTracksViewportWidth
* and scrollableTracksViewportHeight can be used to effectively
* disable scrolling (if they're true) in their respective dimensions.
*
* - Assuming that a scrollbar hasn't been disabled by the
* previous constraint, we need to decide if the scrollbar is going
* to appear to correctly compute the JScrollPanes preferred size.
* To do this we compare the preferredSize of the viewport (the
* extentSize) to the preferredSize of the view. Although we're
* not responsible for laying out the view we'll assume that the
* JViewport will always give it its preferredSize.
*/
if ((vsb != null) && (vsbPolicy != VERTICAL_SCROLLBAR_NEVER)) {
boolean considerVsbWidth = vsb.isOpaque() || isAlwaysOpaque(view);
if (vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) {
if (considerVsbWidth) prefWidth += vsb.getPreferredSize().width;
}
else if ((viewSize != null) && (extentSize != null)) {
boolean canScroll = true;
// If the view is tracking the viewports width we don't bother with a horizontal scrollbar.
// If the view is tracking the viewports height we don't bother with a vertical scrollbar.
boolean viewTracksViewportWidth = false;
boolean viewTracksViewportHeight = false;
// Don't bother checking the Scrollable methods if there is no room for the viewport,
// we aren't going to show any scroll bars in this case anyway.
if (view instanceof Scrollable) {
canScroll = !((Scrollable)view).getScrollableTracksViewportHeight();
Scrollable scrollable = (Scrollable)view;
viewTracksViewportWidth = scrollable.getScrollableTracksViewportWidth();
viewTracksViewportHeight = scrollable.getScrollableTracksViewportHeight();
}
if (canScroll && viewSize.height > extentSize.height && considerVsbWidth) {
prefWidth += vsb.getPreferredSize().width;
Dimension viewportExtentSize = viewport.getPreferredSize();
Dimension viewPreferredSize = view.getPreferredSize();
if (view instanceof JComponent && !view.isPreferredSizeSet()) {
Insets insets = JBViewport.getViewInsets((JComponent)view);
JBInsets.removeFrom(viewportExtentSize, insets);
JBInsets.removeFrom(viewPreferredSize, insets);
}
result.width += viewportExtentSize.width;
result.height += viewportExtentSize.height;
if (!viewTracksViewportHeight && vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
if (viewPreferredSize.height > viewportExtentSize.height || 0 != view.getY()) {
vsbPolicy = VERTICAL_SCROLLBAR_ALWAYS;
}
}
if (!viewTracksViewportWidth && vsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED) {
if (viewPreferredSize.width > viewportExtentSize.width || 0 != view.getX()) {
vsbPolicy = HORIZONTAL_SCROLLBAR_ALWAYS;
}
}
}
}
if (vsb != null && vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS) result.width += vsb.getPreferredSize().width;
if (hsb != null && hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS) result.height += hsb.getPreferredSize().height;
if ((hsb != null) && (hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER)) {
boolean considerHsbHeight = hsb.isOpaque() || isAlwaysOpaque(view);
if (hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS && considerHsbHeight) {
prefHeight += hsb.getPreferredSize().height;
}
else if ((viewSize != null) && (extentSize != null)) {
boolean canScroll = true;
if (view instanceof Scrollable) {
canScroll = !((Scrollable)view).getScrollableTracksViewportWidth();
}
if (canScroll && (viewSize.width > extentSize.width) && considerHsbHeight) {
prefHeight += hsb.getPreferredSize().height;
}
}
}
if (rowHead != null && rowHead.isVisible()) result.width += rowHead.getPreferredSize().width;
if (colHead != null && colHead.isVisible()) result.height += colHead.getPreferredSize().height;
return new Dimension(prefWidth, prefHeight);
return result;
}
private static boolean isAlwaysOpaque(Component view) {
@@ -6,10 +6,12 @@ import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.ui.TypingTarget;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.components.JBScrollPane.Alignment;
import com.intellij.ui.table.JBTable;
import com.intellij.util.MethodInvocator;
import com.intellij.util.ui.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -61,8 +63,8 @@ public class JBViewport extends JViewport implements ZoomableViewport {
Component view = viewport.getView();
if (view instanceof Scrollable) {
Scrollable scrollable = (Scrollable)view;
if (view instanceof JBList) return scrollable.getPreferredScrollableViewportSize();
if (view instanceof JList) return JBList.getPreferredScrollableViewportSize((JList)view);
if (view instanceof JList) return getPreferredScrollableViewportSize((JList)view);
if (view instanceof JTree) return getPreferredScrollableViewportSize((JTree)view);
return scrollable.getPreferredScrollableViewportSize();
}
if (view != null) {
@@ -322,6 +324,7 @@ public class JBViewport extends JViewport implements ZoomableViewport {
}
static Insets getViewInsets(JComponent view) {
Border border = view.getBorder();
if (border instanceof ViewBorder) {
ViewBorder vb = (ViewBorder)border;
@@ -513,4 +516,100 @@ public class JBViewport extends JViewport implements ZoomableViewport {
}
}
}
private static Class<?> getPreferredScrollableViewportSizeDeclaringClass(@NotNull Scrollable scrollable) {
try {
return scrollable.getClass().getMethod("getPreferredScrollableViewportSize").getDeclaringClass();
}
catch (Exception exception) {
return null;
}
}
@NotNull
private static Dimension getPreferredScrollableViewportSize(@NotNull JList list) {
if (JList.class != getPreferredScrollableViewportSizeDeclaringClass(list)) {
return list.getPreferredScrollableViewportSize();
}
Dimension size = list.getPreferredSize();
if (size == null) return new Dimension();
if (JList.VERTICAL != list.getLayoutOrientation()) return size;
int fixedWidth = list.getFixedCellWidth();
int fixedHeight = list.getFixedCellHeight();
ListModel model = list.getModel();
int modelRows = model == null ? 0 : model.getSize();
if (modelRows <= 0) {
if (fixedWidth <= 0) fixedWidth = Registry.intValue("ide.preferred.scrollable.viewport.fixed.width");
if (fixedWidth <= 0) fixedWidth = JBUI.scale(256); // scaled value from JDK
if (fixedHeight <= 0) fixedHeight = Registry.intValue("ide.preferred.scrollable.viewport.fixed.height");
if (fixedHeight <= 0) fixedHeight = JBUI.scale(16); // scaled value from JDK
}
int visibleRows = list.getVisibleRowCount();
if (visibleRows <= 0) visibleRows = Registry.intValue("ide.preferred.scrollable.viewport.visible.rows");
boolean addExtraSpace = 0 < visibleRows && visibleRows < modelRows && Registry.is("ide.preferred.scrollable.viewport.extra.space");
Insets insets = list.getInsets();
size.height = insets != null ? insets.top + insets.bottom : 0;
if (0 < fixedWidth && 0 < fixedHeight) {
size.width = insets != null ? insets.left + insets.right + fixedWidth : fixedWidth;
size.height += fixedHeight * visibleRows;
if (addExtraSpace) size.height += fixedHeight / 2;
}
else if (addExtraSpace) {
Rectangle bounds = list.getCellBounds(visibleRows, visibleRows);
if (bounds != null) size.height = bounds.y + bounds.height / 2;
}
else if (visibleRows > 0) {
int lastRow = Math.min(visibleRows, modelRows) - 1;
Rectangle bounds = list.getCellBounds(lastRow, lastRow);
if (bounds != null) {
size.height = bounds.y + bounds.height;
if (insets != null) size.height += insets.bottom;
}
}
return size;
}
@NotNull
private static Dimension getPreferredScrollableViewportSize(@NotNull JTree tree) {
if (JTree.class != getPreferredScrollableViewportSizeDeclaringClass(tree)) {
return tree.getPreferredScrollableViewportSize();
}
Dimension size = tree.getPreferredSize();
if (size == null) return new Dimension();
int fixedHeight = tree.getRowHeight();
int modelRows = tree.getRowCount();
if (modelRows <= 0) {
if (fixedHeight <= 0) fixedHeight = Registry.intValue("ide.preferred.scrollable.viewport.fixed.height");
if (fixedHeight <= 0) fixedHeight = JBUI.scale(16);
}
int visibleRows = tree.getVisibleRowCount();
if (visibleRows <= 0) visibleRows = Registry.intValue("ide.preferred.scrollable.viewport.visible.rows");
boolean addExtraSpace = Registry.is("ide.preferred.scrollable.viewport.extra.space");
Insets insets = tree.getInsets();
size.height = insets != null ? insets.top + insets.bottom : 0;
if (0 < fixedHeight) {
size.height += fixedHeight * visibleRows;
if (addExtraSpace) size.height += fixedHeight / 2;
}
else if (visibleRows > 0) {
int lastRow = Math.min(visibleRows, modelRows - 1);
Rectangle bounds = tree.getRowBounds(lastRow);
if (bounds != null) {
size.height = bounds.y + bounds.height * (visibleRows - lastRow);
if (addExtraSpace) {
size.height += bounds.height / 2;
}
else if (insets != null) {
size.height += insets.bottom;
}
}
}
return size;
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2012 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.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.treeStructure;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
@@ -477,10 +463,6 @@ public class SimpleTree extends Tree implements CellEditorListener {
return (DefaultTreeModel)getModel();
}
public Dimension getPreferredScrollableViewportSize() {
return super.getPreferredSize();
}
public NodeRenderer getRenderer() {
return (NodeRenderer)getCellRenderer();
}
@@ -154,8 +154,6 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im
private State myState = new State();
private final Map<String, String> myNameCache = Collections.synchronizedMap(new THashMap<String, String>());
private Set<String> myDuplicatesCache = null;
private boolean isDuplicatesCacheUpdating = false;
private boolean myBatchOpening;
protected RecentProjectsManagerBase(@NotNull MessageBus messageBus) {
@@ -410,26 +408,14 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im
}
private Set<String> getDuplicateProjectNames(Set<String> openedPaths, Set<String> recentPaths) {
if (myDuplicatesCache != null) {
return myDuplicatesCache;
Set<String> names = ContainerUtil.newHashSet();
Set<String> duplicates = ContainerUtil.newHashSet();
for (String path : ContainerUtil.concat(openedPaths, recentPaths)) {
if (!names.add(getProjectName(path))) {
duplicates.add(path);
}
}
if (!isDuplicatesCacheUpdating) {
isDuplicatesCacheUpdating = true; //assuming that this check happens only on EDT. So, no synchronised block or double-checked locking needed
Set<String> names = ContainerUtil.newHashSet();
final HashSet<String> duplicates = ContainerUtil.newHashSet();
ArrayList<String> list = ContainerUtil.newArrayList(ContainerUtil.concat(openedPaths, recentPaths));
ApplicationManager.getApplication().executeOnPooledThread(() -> {
for (String path : list) {
if (!names.add(getProjectName(path))) {
duplicates.add(path);
}
}
myDuplicatesCache = duplicates;
isDuplicatesCacheUpdating = false;
});
}
return ContainerUtil.newHashSet();
return duplicates;
}
@Override
@@ -113,10 +113,10 @@ public class ContextMenuImpl extends JPanel implements Disposable {
}
private void toggleContextToolbar(final boolean show) {
myActionToolbar.updateActionsImmediately();
if (((Container)myActionToolbar).getComponentCount() == 0) {
return;
}
myActionToolbar.updateActionsImmediately();
if (myShow != show) {
myShow = show;
@@ -315,30 +315,13 @@ public class MinusculeMatcher implements Matcher {
int nameIndex,
boolean allowSpecialChars,
boolean isAsciiName) {
boolean star = isPatternChar(patternIndex - 1, '*');
final char p = myPattern[patternIndex];
boolean wordStartsOnly = !isPatternChar(patternIndex - 1, '*') && !isWordSeparator[patternIndex];
while (true) {
int nextOccurrence = star || isWordSeparator[patternIndex] ?
indexOfIgnoreCase(name, nameIndex + 1, p, patternIndex, isAsciiName) :
indexOfWordStart(name, patternIndex, nameIndex);
int nextOccurrence = findNextPatternCharOccurrence(name, nameIndex, patternIndex, isAsciiName, allowSpecialChars, wordStartsOnly);
if (nextOccurrence < 0) {
return null;
}
// pattern humps are allowed to match in words separated by " ()", lowercase characters aren't
if (!allowSpecialChars && !myHasSeparators && !myHasHumps && StringUtil.containsAnyChar(name, myHardSeparators, nameIndex, nextOccurrence)) {
return null;
}
// if the user has typed a dot, don't skip other dots between humps
// but one pattern dot may match several name dots
if (!allowSpecialChars && myHasDots && !isPatternChar(patternIndex - 1, '.') && StringUtil.contains(name, nameIndex, nextOccurrence, '.')) {
return null;
}
// uppercase should match either uppercase or a word start
if (!isUpperCase[patternIndex] ||
Character.isUpperCase(name.charAt(nextOccurrence)) ||
NameUtil.isWordStart(name, nextOccurrence) ||
// accept uppercase matching lowercase if the whole prefix is uppercase and case sensitivity allows that
!myHasHumps && myOptions != NameUtil.MatchingCaseSensitivity.ALL) {
if (seemsLikeFragmentStart(name, patternIndex, nextOccurrence)) {
FList<TextRange> ranges = matchFragment(name, patternIndex, nextOccurrence, isAsciiName);
if (ranges != null) {
return ranges;
@@ -348,6 +331,37 @@ public class MinusculeMatcher implements Matcher {
}
}
private int findNextPatternCharOccurrence(@NotNull String name,
int startAt,
int patternIndex,
boolean isAsciiName,
boolean allowSpecialChars, boolean wordStartsOnly) {
int next = wordStartsOnly
? indexOfWordStart(name, patternIndex, startAt)
: indexOfIgnoreCase(name, startAt + 1, myPattern[patternIndex], patternIndex, isAsciiName);
// pattern humps are allowed to match in words separated by " ()", lowercase characters aren't
if (!allowSpecialChars && !myHasSeparators && !myHasHumps && StringUtil.containsAnyChar(name, myHardSeparators, startAt, next)) {
return -1;
}
// if the user has typed a dot, don't skip other dots between humps
// but one pattern dot may match several name dots
if (!allowSpecialChars && myHasDots && !isPatternChar(patternIndex - 1, '.') && StringUtil.contains(name, startAt, next, '.')) {
return -1;
}
return next;
}
private boolean seemsLikeFragmentStart(@NotNull String name, int patternIndex, int nextOccurrence) {
// uppercase should match either uppercase or a word start
return !isUpperCase[patternIndex] ||
Character.isUpperCase(name.charAt(nextOccurrence)) ||
NameUtil.isWordStart(name, nextOccurrence) ||
// accept uppercase matching lowercase if the whole prefix is uppercase and case sensitivity allows that
!myHasHumps && myOptions != NameUtil.MatchingCaseSensitivity.ALL;
}
private boolean charEquals(char patternChar, int patternIndex, char c, boolean isIgnoreCase) {
return patternChar == c ||
isIgnoreCase && (toLowerCase[patternIndex] == c || toUpperCase[patternIndex] == c);
@@ -137,7 +137,7 @@ public class MoveChangesToAnotherListAction extends AnAction implements DumbAwar
List<VirtualFile> unversionedFiles = ContainerUtil.newArrayList();
final List<VirtualFile> changedFiles = ContainerUtil.newArrayList();
VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
if (files != null) {
if (files != null && changesList.isEmpty()) {
changesList.addAll(getChangesForSelectedFiles(project, files, unversionedFiles, changedFiles));
}
@@ -24,15 +24,18 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.actions.MoveChangesToAnotherListAction;
import com.intellij.openapi.vcs.changes.ui.ChangeListChooser;
import com.intellij.openapi.vcs.ex.PartialLocalLineStatusTracker.LocalRange;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.Collections.singletonList;
public class MoveChangesLineStatusAction extends LineStatusActionBase {
@Override
protected boolean isEnabled(@NotNull LineStatusTrackerBase<?> tracker, @NotNull Editor editor) {
@@ -51,36 +54,46 @@ public class MoveChangesLineStatusAction extends LineStatusActionBase {
public static void moveToAnotherChangelist(@NotNull PartialLocalLineStatusTracker tracker, @NotNull BitSet selectedLines) {
Project project = tracker.getProject();
List<PartialLocalLineStatusTracker.LocalRange> ranges = tracker.getRangesForLines(selectedLines);
List<LocalRange> ranges = tracker.getRangesForLines(selectedLines);
if (ranges == null || ranges.isEmpty()) return;
Set<String> selectedListIds = ContainerUtil.map2Set(ranges, range -> range.getChangelistId());
LocalChangeList targetList = askTargetChangelist(project, selectedListIds);
LocalChangeList targetList = askTargetChangelist(project, ranges, tracker);
if (targetList == null) return;
tracker.moveToChangelist(selectedLines, targetList);
}
public static void moveToAnotherChangelist(@NotNull PartialLocalLineStatusTracker tracker, @NotNull PartialLocalLineStatusTracker.LocalRange range) {
public static void moveToAnotherChangelist(@NotNull PartialLocalLineStatusTracker tracker, @NotNull LocalRange range) {
Project project = tracker.getProject();
Set<String> selectedListIds = Collections.singleton(range.getChangelistId());
LocalChangeList targetList = askTargetChangelist(project, selectedListIds);
LocalChangeList targetList = askTargetChangelist(project, singletonList(range), tracker);
if (targetList == null) return;
tracker.moveToChangelist(range, targetList);
}
@Nullable
private static LocalChangeList askTargetChangelist(Project project, @NotNull Set<String> selectedListIds) {
private static LocalChangeList askTargetChangelist(Project project,
@NotNull List<LocalRange> selectedRanges,
@NotNull PartialLocalLineStatusTracker tracker) {
Set<String> selectedListIds = ContainerUtil.map2Set(selectedRanges, range -> range.getChangelistId());
Set<String> remainingTrackerListIds = new HashSet<>(tracker.getAffectedChangeListsIds());
remainingTrackerListIds.removeAll(selectedListIds);
ChangeListManager clm = ChangeListManager.getInstance(project);
List<LocalChangeList> allChangelists = clm.getChangeListsCopy();
List<LocalChangeList> nonAffectedLists = ContainerUtil.filter(allChangelists, list -> !selectedListIds.contains(list.getId()));
List<LocalChangeList> remainingTrackerLists = ContainerUtil.filter(allChangelists, list -> remainingTrackerListIds.contains(list.getId()));
List<LocalChangeList> suggestedLists = nonAffectedLists.isEmpty()
? Collections.singletonList(clm.getDefaultChangeList())
? singletonList(clm.getDefaultChangeList())
: nonAffectedLists;
ChangeList defaultSelection = MoveChangesToAnotherListAction.guessPreferredList(nonAffectedLists);
List<LocalChangeList> preferedLists = remainingTrackerLists.isEmpty() ? nonAffectedLists : remainingTrackerLists;
ChangeList defaultSelection = MoveChangesToAnotherListAction.guessPreferredList(preferedLists);
ChangeListChooser chooser = new ChangeListChooser(project,
suggestedLists,
defaultSelection,
@@ -277,6 +277,7 @@ abstract class GitImplBase implements Git {
"cannot rebase:",
"conflict",
"unable",
"The file will have its original",
"runnerw:"
};
@@ -3,10 +3,12 @@
*/
package git4idea.config;
import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
@@ -24,7 +26,7 @@ abstract class CachingFileTester<T> {
long currentLastModificationDate = 0L;
try {
currentLastModificationDate = Files.getLastModifiedTime(Paths.get(filePath)).toMillis();
currentLastModificationDate = Files.getLastModifiedTime(Paths.get(resolveAgainstEnvPath(filePath))).toMillis();
if (result == null || result.getFileLastModifiedTimestamp() != currentLastModificationDate) {
result = new TestResult(testFile(filePath), currentLastModificationDate);
}
@@ -40,6 +42,17 @@ abstract class CachingFileTester<T> {
return result;
}
@NotNull
private static String resolveAgainstEnvPath(@NotNull String filePath) {
if (!filePath.contains(File.separator)) {
File exeFile = PathEnvironmentVariableUtil.findInPath(filePath);
if (exeFile != null) {
return exeFile.getPath();
}
}
return filePath;
}
@Nullable
public TestResult getCachedResultForFile(@NotNull String filePath) {
return myFileTestMap.get(filePath);
@@ -23,6 +23,8 @@ import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.impl.HashImpl;
import com.intellij.vcsUtil.VcsFileUtil;
import com.intellij.vcsUtil.VcsUtil;
import git4idea.GitUtil;
@@ -95,27 +97,27 @@ public class GitIndexUtil {
}
@NotNull
public static String write(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull byte[] bytes,
boolean executable) throws VcsException {
public static Hash write(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull byte[] bytes,
boolean executable) throws VcsException {
return write(repository, filePath, new ByteArrayInputStream(bytes), executable);
}
@NotNull
public static String write(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull InputStream content,
boolean executable) throws VcsException {
String hash = hashObject(repository, filePath, content);
public static Hash write(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull InputStream content,
boolean executable) throws VcsException {
Hash hash = hashObject(repository, filePath, content);
updateIndex(repository, filePath, hash, executable);
return hash;
}
@NotNull
private static String hashObject(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull InputStream content) throws VcsException {
private static Hash hashObject(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull InputStream content) throws VcsException {
GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.HASH_OBJECT);
h.setSilent(true);
h.addParameters("-w", "--stdin");
@@ -135,19 +137,19 @@ public class GitIndexUtil {
notNull(GitVcs.getInstance(repository.getProject())).showErrors(h.errors(), "Applying index modifications");
throw h.errors().get(0);
}
return output.trim();
return HashImpl.build(output.trim());
}
private static void updateIndex(@NotNull GitRepository repository,
@NotNull FilePath filePath,
@NotNull String blobHash,
@NotNull Hash blobHash,
boolean isExecutable) throws VcsException {
String mode = isExecutable ? EXECUTABLE_MODE : DEFAULT_MODE;
String path = VcsFileUtil.relativePath(repository.getRoot(), filePath);
GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.UPDATE_INDEX);
h.setSilent(true);
h.addParameters("--cacheinfo", mode + "," + blobHash + "," + path);
h.addParameters("--cacheinfo", mode + "," + blobHash.asString() + "," + path);
h.endOptions();
Git.getInstance().runCommandWithoutCollectingOutput(h).getOutputOrThrow();
}
@@ -112,6 +112,7 @@
<projectService serviceImplementation="com.intellij.tasks.impl.TaskProjectConfiguration"/>
<applicationService serviceImplementation="com.intellij.tasks.config.RecentTaskRepositories"/>
<applicationService serviceImplementation="com.intellij.tasks.config.TaskSettings"/>
<search.optionContributor implementation="com.intellij.tasks.config.TaskSearchableOptionContributor"/>
<lang.documentationProvider language="TEXT" implementationClass="com.intellij.tasks.doc.TaskDocumentationProvider"/>
@@ -8,6 +8,7 @@ import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.options.BaseConfigurable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction;
@@ -40,9 +41,11 @@ import java.util.List;
* @author Dmitry Avdeev
*/
@SuppressWarnings("unchecked")
public class TaskRepositoriesConfigurable extends BaseConfigurable implements Configurable.NoScroll {
public class TaskRepositoriesConfigurable extends BaseConfigurable implements Configurable.NoScroll, SearchableConfigurable {
public static final String ID = "tasks.servers";
private static final String EMPTY_PANEL = "empty.panel";
private JPanel myPanel;
private JPanel myServersPanel;
private final JBList myRepositoriesList;
@@ -257,6 +260,20 @@ public class TaskRepositoriesConfigurable extends BaseConfigurable implements Co
}
}
@NotNull
@Override
public String getId() {
return ID;
}
@Nullable
@Override
public Runnable enableSearch(String option) {
TaskRepository matched =
myRepositories.stream().filter(repository -> repository.getRepositoryType().getName().contains(option)).findFirst().orElse(null);
return matched == null ? null : () -> myRepositoriesList.setSelectedValue(matched, true);
}
private abstract class AddServerAction extends IconWithTextAction implements DumbAware {
public AddServerAction(TaskRepositorySubtype subtype) {
@@ -0,0 +1,17 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.tasks.config;
import com.intellij.ide.ui.search.SearchableOptionContributor;
import com.intellij.ide.ui.search.SearchableOptionProcessor;
import com.intellij.tasks.TaskRepositoryType;
import org.jetbrains.annotations.NotNull;
public class TaskSearchableOptionContributor extends SearchableOptionContributor {
@Override
public void processOptions(@NotNull SearchableOptionProcessor processor) {
TaskRepositoryType[] types = TaskRepositoryType.getRepositoryTypes();
for (TaskRepositoryType type : types) {
processor.addOptions(type.getName(), null, null, TaskRepositoriesConfigurable.ID, null, true);
}
}
}