Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Dmitry Jemerov
2010-12-19 11:29:04 +03:00
29 changed files with 607 additions and 211 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2010 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,12 +19,14 @@ package com.intellij.injected.editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.event.SelectionListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author cdr
@@ -44,10 +46,22 @@ public class SelectionModelWindow implements SelectionModel {
return myDocument.hostToInjected(myHostModel.getSelectionStart());
}
@Nullable
@Override
public VisualPosition getSelectionStartPosition() {
return myHostModel.getSelectionStartPosition();
}
public int getSelectionEnd() {
return myDocument.hostToInjected(myHostModel.getSelectionEnd());
}
@Nullable
@Override
public VisualPosition getSelectionEndPosition() {
return myHostModel.getSelectionEndPosition();
}
public String getSelectedText() {
return myHostModel.getSelectedText();
}
@@ -56,6 +70,12 @@ public class SelectionModelWindow implements SelectionModel {
return myDocument.hostToInjected(myHostModel.getLeadSelectionOffset());
}
@Nullable
@Override
public VisualPosition getLeadSelectionPosition() {
return myHostModel.getLeadSelectionPosition();
}
public boolean hasSelection() {
return myHostModel.hasSelection();
}
@@ -65,6 +85,12 @@ public class SelectionModelWindow implements SelectionModel {
myHostModel.setSelection(hostRange.getStartOffset(), hostRange.getEndOffset());
}
@Override
public void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset) {
TextRange hostRange = myDocument.injectedToHost(new ProperTextRange(startOffset, endOffset));
myHostModel.setSelection(startPosition, hostRange.getStartOffset(), endPosition, hostRange.getEndOffset());
}
public void removeSelection() {
myHostModel.removeSelection();
}
@@ -34,6 +34,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
@@ -487,11 +488,14 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec
if (x) {
myBlockSupport.reparseRange(file, startOffset, endOffset, lengthShift, chars);
}
String fileText = file.getText();
String documentText = document.getText();
throw new AssertionError("commitDocument left PSI inconsistent; file len=" + file.getTextLength() +
"; doc len=" + document.getTextLength() +
"; file text=" + file.getText() +
"; doc text=" + document.getText() +
"; old file text=" + oldText);
"; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText) +
";\n file text=" + fileText +
";\n doc text=" + documentText +
";\n old file text=" + oldText);
}
throw new AssertionError("commitDocument left PSI inconsistent: " + file);
@@ -41,10 +41,16 @@ public abstract class PsiManagerEx extends PsiManager {
@NotNull
public abstract ResolveCache getResolveCache();
/**
* @param runnable to be run before <b>physical</b> PSI change
*/
public abstract void registerRunnableToRunOnChange(@NotNull Runnable runnable);
public abstract void registerWeakRunnableToRunOnChange(@NotNull Runnable runnable);
/**
* @param runnable to be run before <b>physical</b> or <b>non-physical</b> PSI change
*/
public abstract void registerRunnableToRunOnAnyChange(@NotNull Runnable runnable);
public abstract void registerRunnableToRunAfterAnyChange(@NotNull Runnable runnable);
@@ -111,8 +111,10 @@ public class VariableInplaceRenamer {
return false;
}
VirtualFile vFile = myElementToRename.getContainingFile().getVirtualFile();
SearchScope referencesSearchScope = vFile == null || ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(vFile)
final FileViewProvider fileViewProvider = myElementToRename.getContainingFile().getViewProvider();
VirtualFile file = getTopLevelVirtualFile(fileViewProvider);
SearchScope referencesSearchScope = file == null || ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(file)
? ProjectScope.getProjectScope(myElementToRename.getProject())
: new LocalSearchScope(myElementToRename.getContainingFile());
@@ -120,9 +122,6 @@ public class VariableInplaceRenamer {
addReferenceAtCaret(refs);
final FileViewProvider fileViewProvider = myElementToRename.getContainingFile().getViewProvider();
VirtualFile file = getTopLevelVirtualFile(fileViewProvider);
for (PsiReference ref : refs) {
final FileViewProvider usageViewProvider = ref.getElement().getContainingFile().getViewProvider();
@@ -39,6 +39,12 @@ public interface SelectionModel {
*/
int getSelectionStart();
/**
* @return object that encapsulates information about visual position of selected text start if any
*/
@Nullable
VisualPosition getSelectionStartPosition();
/**
* Returns the end offset in the document of the selected text range, or the caret
* position if there is currently no selection.
@@ -47,6 +53,12 @@ public interface SelectionModel {
*/
int getSelectionEnd();
/**
* @return object that encapsulates information about visual position of selected text end if any;
*/
@Nullable
VisualPosition getSelectionEndPosition();
/**
* Returns the text selected in the editor (or the concatenation of text ranges selected
* in each line, if block selection mode is used).
@@ -66,6 +78,12 @@ public interface SelectionModel {
*/
int getLeadSelectionOffset();
/**
* @return object that encapsulates information about visual position from which the user started to extend the selection if any
*/
@Nullable
VisualPosition getLeadSelectionPosition();
/**
* Checks if a range of text is currently selected in regular (non-block) selection mode.
*
@@ -83,6 +101,18 @@ public interface SelectionModel {
*/
void setSelection(int startOffset, int endOffset);
/**
* Selects target range based on its visual boundaries.
* <p/>
* That is the case for soft wraps-aware processing where the whole soft wraps virtual space is matched to the same offset.
*
* @param startPosition start visual position of the text range to select
* @param endPosition end visual position of the text range to select
* @param startOffset start selection offset
* @param endOffset end selection offset
*/
void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset);
/**
* Removes the selection in the editor.
*/
@@ -16,6 +16,7 @@
package com.intellij.openapi.editor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Represents a visual position in the editor. Visual positions take folding into account -
@@ -38,6 +39,27 @@ public class VisualPosition {
this.column = column;
}
/**
* Allows to answer if current visual position is located after the given one.
* <p/>
* One visual position is considered to be 'after' another only if one of the following is true:
* <pre>
* <ul>
* <li>its visual line is greater;</li>
* <li>it has the same visual line but its column is greater;</li>
* </ul>
* </pre>
*
* @param other visual position to compare with the current one
* @return <code>true</code> if current position is 'after' the given one; <code>false</code> otherwise
*/
public boolean after(@NotNull VisualPosition other) {
if (line == other.line) {
return column > other.column;
}
return line > other.line;
}
@NonNls
public String toString() {
return "VisualPosition: line = " + line + " column = " + column;
@@ -20,6 +20,7 @@ import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.OutputStream;
@@ -33,6 +34,7 @@ public class RunnerMediator {
private static final char IAC = (char)5;
private static final char BRK = (char)3;
private static final String STANDARD_RUNNERW = "runnerw.exe";
/**
* Creates default runner mediator
@@ -84,10 +86,17 @@ public class RunnerMediator {
return new CustomDestroyProcessHandler(process, commandLine);
}
@Nullable
private String getRunnerPath() {
if (File.separatorChar == '\\') {
return "runnerw.exe";
if (isWindows()) {
final String path = System.getenv("IDEA_RUNNERW");
if (path != null && new File(path).exists()) {
return path;
}
if (new File(STANDARD_RUNNERW).exists()) {
return STANDARD_RUNNERW;
}
return null;
}
else {
throw new IllegalStateException("There is no need of runner under unix based OS");
@@ -95,8 +104,11 @@ public class RunnerMediator {
}
private void injectRunnerCommand(@NotNull GeneralCommandLine commandLine) {
commandLine.getParametersList().addAt(0, commandLine.getExePath());
commandLine.setExePath(getRunnerPath());
final String path = getRunnerPath();
if (path != null) {
commandLine.getParametersList().addAt(0, commandLine.getExePath());
commandLine.setExePath(path);
}
}
public static boolean isUnix() {
@@ -923,6 +923,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (x >= px) {
onSoftWrapDrawing = true;
}
else {
column++;
}
break outer;
}
else {
@@ -1270,7 +1273,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (endOffset > myDocument.getTextLength()) {
endOffset = myDocument.getTextLength();
}
if (startOffset < endOffset) {
// We do repaint in case of equal offsets because there is a possible case that there is a soft wrap at the same offset and
// it does occupy particular amount of visual space that may be necessary to repaint.
if (startOffset <= endOffset) {
int startLine = myDocument.getLineNumber(startOffset);
int endLine = myDocument.getLineNumber(endOffset);
repaintLines(startLine, endLine);
@@ -1711,23 +1717,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int start = logicalPositionToOffset(logicalPosition);
getSoftWrapModel().registerSoftWrapsIfNecessary();
// There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position
// has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset.
// Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary.
TIntHashSet softWrapsToSkip = new TIntHashSet();
SoftWrap softWrap = getSoftWrapModel().getSoftWrap(start);
if (softWrap != null) {
softWrapsToSkip.add(softWrap.getStart());
if (position.y == getCaretModel().getVisualPosition().line * getLineHeight()) {
// There is a possible case that target clip points to soft wrap-introduced visual line and that it's an active
// line (caret cursor is located on it). We want to draw corresponding 'caret line' background for soft wraps-introduced
// virtual space then.
Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR);
drawBackground(g, caretRowColor, softWrap.getIndentInPixels(), position, defaultBackground, clip);
}
position.x = softWrap.getIndentInPixels();
}
IterationState iterationState = new IterationState(this, start, paintSelection());
LineIterator lIterator = createLineIterator();
@@ -1742,6 +1731,31 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
CharSequence text = myDocument.getCharsNoThreadCheck();
int lastLineIndex = Math.max(0, myDocument.getLineCount() - 1);
// There is a possible case that we need to draw background from the start of soft wrap-introduced visual line. Given position
// has valid 'y' coordinate then at it shouldn't be affected by soft wrap that corresponds to the visual line start offset.
// Hence, we store information about soft wrap to be skipped for further processing and adjust 'x' coordinate value if necessary.
TIntHashSet softWrapsToSkip = new TIntHashSet();
SoftWrap softWrap = getSoftWrapModel().getSoftWrap(start);
if (softWrap != null) {
softWrapsToSkip.add(softWrap.getStart());
Color color = null;
if (!backColor.equals(defaultBackground)) {
color = backColor;
}
// There is a possible case that target clip points to soft wrap-introduced visual line and that it's an active
// line (caret cursor is located on it). We want to draw corresponding 'caret line' background for soft wraps-introduced
// virtual space then.
if (color == null && position.y == getCaretModel().getVisualPosition().line * getLineHeight()) {
color = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR);
}
if (color != null) {
drawBackground(g, color, softWrap.getIndentInPixels(), position, defaultBackground, clip);
}
position.x = softWrap.getIndentInPixels();
}
// There is a possible case that caret is located at soft-wrapped line. We don't need to paint caret row background
// on a last visual line of that soft-wrapped line then. Below is a holder for the flag that indicates if caret row
// background is already drawn.
@@ -1901,7 +1915,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (startToUse < softWrapStart) {
position.x = drawBackground(g, backColor, text.subSequence(startToUse, softWrapStart), position, fontType, defaultBackground, clip);
}
drawSoftWrap(g, softWrap, position, fontType, defaultBackground, clip, caretRowPainted);
boolean drawCustomBackgroundAtSoftWrapVirtualSpace =
backColor != defaultBackground && (softWrapStart > start || myLastBackgroundColor == backColor);
drawSoftWrap(
g, softWrap, position, fontType, backColor, drawCustomBackgroundAtSoftWrapVirtualSpace, defaultBackground, clip, caretRowPainted
);
startToUse = softWrapStart;
}
@@ -1911,65 +1929,157 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return position.x;
}
private void drawSoftWrap(Graphics g, SoftWrap softWrap, Point position, int fontType, Color defaultBackground, Rectangle clip,
boolean[] caretRowPainted) {
private void drawSoftWrap(Graphics g, SoftWrap softWrap, Point position, int fontType, Color backColor,
boolean drawCustomBackgroundAtSoftWrapVirtualSpace, Color defaultBackground, Rectangle clip,
boolean[] caretRowPainted)
{
// The main idea is to to do the following:
// *) update given drawing position coordinates in accordance with the current soft wrap;
// *) draw 'active line' background at soft wrap-introduced virtual space if necessary;
// *) draw background at soft wrap-introduced virtual space if necessary;
CharSequence softWrapText = softWrap.getText();
int activeRowY = getCaretModel().getVisualPosition().line * getLineHeight();
if (position.y == activeRowY) {
int afterSoftWrapWidth = clip.x + clip.width - position.x;
if (drawCustomBackgroundAtSoftWrapVirtualSpace && backColor != null) {
drawBackground(g, backColor, afterSoftWrapWidth, position, defaultBackground, clip);
}
else if (position.y == activeRowY) {
// Draw 'active line' background after soft wrap.
Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR);
drawBackground(g, caretRowColor, clip.x + clip.width - position.x, position, defaultBackground, clip);
drawBackground(g, caretRowColor, afterSoftWrapWidth, position, defaultBackground, clip);
caretRowPainted[0] = true;
}
paintSelectionOnFirstSoftWrapLineIfNecessary(g, position, clip, defaultBackground, fontType);
int i = CharArrayUtil.lastIndexOf(softWrapText, "\n", softWrapText.length()) + 1;
position.x = getTextSegmentWidth(softWrapText.subSequence(i, softWrapText.length()), 0, fontType, clip);
position.x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
int width = getTextSegmentWidth(softWrapText.subSequence(i, softWrapText.length()), 0, fontType, clip)
+ getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
position.x = 0;
position.y += getLineHeight();
if (position.y == activeRowY) {
if (drawCustomBackgroundAtSoftWrapVirtualSpace && backColor != null) {
drawBackground(g, backColor, width, position, defaultBackground, clip);
}
else if (position.y == activeRowY) {
// Draw 'active line' background for the soft wrap-introduced virtual space.
Color caretRowColor = getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR);
drawBackground(g, caretRowColor, position.x, new Point(0, activeRowY), defaultBackground, clip);
drawBackground(g, caretRowColor, width, position, defaultBackground, clip);
}
// The code below draws background for soft wrap-introduced virtual space. It's is considered that we don't want
// to do that for now. Uncomment if that decision is changed.
//position.x = drawBackground(
// g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED), position,
// defaultBackground, clip
//);
//
//CharSequence softWrapText = softWrap.getText();
//int start = 0;
//for (
// int end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n");
// start < softWrapText.length() && end < softWrapText.length();
// end = CharArrayUtil.shiftForwardUntil(softWrapText, start, "\n"))
//{
// drawBackground(g, backColor, softWrapText.subSequence(start, end), position, fontType, defaultBackground, clip);
// start = end + 1;
// position.x = 0;
// position.y += getLineHeight();
//}
//
//if (start < softWrapText.length()) {
// position.x = drawBackground(
// g, backColor, softWrapText.subSequence(start, softWrapText.length()), position, fontType, defaultBackground, clip
// );
//}
//
//position.x = drawBackground(
// g, backColor, getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP), position,
// defaultBackground, clip
//);
position.x = 0;
paintSelectionOnSecondSoftWrapLineIfNecessary(g, position, clip, defaultBackground, fontType, softWrap);
position.x = width;
}
/**
* End user is allowed to perform selection by visual coordinates (e.g. by dragging mouse with left button hold). There is a possible
* case that such a move intersects with soft wrap introduced virtual space. We want to draw corresponding selection background
* there then.
* <p/>
* This method encapsulates functionality of drawing selection background on the first soft wrap line (e.g. on a visual line where
* it is applied).
*
* @param g graphics to draw on
* @param position current position (assumed to be position of soft wrap appliance)
* @param clip target drawing area boundaries
* @param defaultBackground default background
* @param fontType current font type
*/
private void paintSelectionOnFirstSoftWrapLineIfNecessary(Graphics g, Point position, Rectangle clip, Color defaultBackground,
int fontType)
{
// There is a possible case that the user performed selection at soft wrap virtual space. We need to paint corresponding background
// there then.
VisualPosition selectionStartPosition = getSelectionModel().getSelectionStartPosition();
VisualPosition selectionEndPosition = getSelectionModel().getSelectionEndPosition();
if (selectionStartPosition == null || selectionEndPosition == null || selectionStartPosition.equals(selectionEndPosition)) {
return;
}
int currentVisualLine = position.y / getLineHeight();
int lastColumn = EditorUtil.getLastVisualLineColumnNumber(this, currentVisualLine);
// Check if the first soft wrap line is within the visual selection.
if (currentVisualLine < selectionStartPosition.line || currentVisualLine > selectionEndPosition.line
|| (currentVisualLine == selectionEndPosition.line && selectionEndPosition.column <= lastColumn)) {
return;
}
// Adjust 'x' if selection starts at soft wrap virtual space.
final int columnsToSkip = selectionStartPosition.column - lastColumn;
if (columnsToSkip > 0) {
position.x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
position.x += (columnsToSkip - 1) * EditorUtil.getSpaceWidth(Font.PLAIN, this);
}
// Calculate selection width.
final int width;
if (selectionEndPosition.line > currentVisualLine) {
width = clip.x + clip.width - position.x;
}
else if (selectionStartPosition.line < currentVisualLine || selectionStartPosition.column <= lastColumn) {
width = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED)
+ (selectionEndPosition.column - lastColumn - 1) * EditorUtil.getSpaceWidth(fontType, this);
}
else {
width = (selectionEndPosition.column - selectionStartPosition.column) * EditorUtil.getSpaceWidth(fontType, this);
}
drawBackground(g, getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR), width, position, defaultBackground, clip);
}
/**
* End user is allowed to perform selection by visual coordinates (e.g. by dragging mouse with left button hold). There is a possible
* case that such a move intersects with soft wrap introduced virtual space. We want to draw corresponding selection background
* there then.
* <p/>
* This method encapsulates functionality of drawing selection background on the second soft wrap line (e.g. on a visual line after
* the one where it is applied).
*
* @param g graphics to draw on
* @param position current position (assumed to be position of soft wrap appliance)
* @param clip target drawing area boundaries
* @param defaultBackground default background
* @param fontType current font type
* @param softWrap target soft wrap which second line virtual space may contain selection
*/
private void paintSelectionOnSecondSoftWrapLineIfNecessary(Graphics g, Point position, Rectangle clip, Color defaultBackground,
int fontType, SoftWrap softWrap)
{
// There is a possible case that the user performed selection at soft wrap virtual space. We need to paint corresponding background
// there then.
VisualPosition selectionStartPosition = getSelectionModel().getSelectionStartPosition();
VisualPosition selectionEndPosition = getSelectionModel().getSelectionEndPosition();
if (selectionStartPosition == null || selectionEndPosition == null || selectionStartPosition.equals(selectionEndPosition)) {
return;
}
int currentVisualLine = position.y / getLineHeight();
// Check if the second soft wrap line is within the visual selection.
if (currentVisualLine < selectionStartPosition.line || currentVisualLine > selectionEndPosition.line
|| (currentVisualLine == selectionStartPosition.line && selectionStartPosition.column >= softWrap.getIndentInColumns())) {
return;
}
// Adjust 'x' if selection starts at soft wrap virtual space.
if (selectionStartPosition.line == currentVisualLine && selectionStartPosition.column > 0) {
position.x += selectionStartPosition.column * EditorUtil.getSpaceWidth(fontType, this);
}
// Calculate selection width.
final int width;
if (selectionEndPosition.line > currentVisualLine || selectionEndPosition.column >= softWrap.getIndentInColumns()) {
width = softWrap.getIndentInPixels() - position.x;
}
else {
width = selectionEndPosition.column * EditorUtil.getSpaceWidth(fontType, this) - position.x;
}
drawBackground(g, getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR), width, position, defaultBackground, clip);
}
private int drawBackground(Graphics g, Color backColor, CharSequence text, Point position, int fontType, Color defaultBackground,
Rectangle clip)
{
@@ -3278,12 +3388,15 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
SelectionModel selectionModel = getSelectionModel();
int oldSelectionStart = selectionModel.getLeadSelectionOffset();
VisualPosition oldVisLeadSelectionStart = selectionModel.getLeadSelectionPosition();
int oldCaretOffset = getCaretModel().getOffset();
LogicalPosition oldLogicalCaret = getCaretModel().getLogicalPosition();
VisualPosition oldVisualCaret = getCaretModel().getVisualPosition();
moveCaretToScreenPos(x, y);
getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
int newCaretOffset = getCaretModel().getOffset();
VisualPosition newVisualCaret = getCaretModel().getVisualPosition();
int caretShift = newCaretOffset - mySavedSelectionStart;
if (myMousePressedEvent != null && getMouseEventArea(myMousePressedEvent) != EditorMouseEventArea.EDITING_AREA &&
@@ -3331,7 +3444,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
if (!myMousePressedInsideSelection) {
selectionModel.setSelection(oldSelectionStart, newCaretOffset);
if (oldVisLeadSelectionStart != null) {
selectionModel.setSelection(oldVisLeadSelectionStart, oldSelectionStart, newVisualCaret, newCaretOffset);
}
else {
selectionModel.setSelection(oldSelectionStart, newCaretOffset);
}
}
else {
if (caretShift != 0) {
@@ -50,6 +50,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.EmptyClipboardOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
@@ -70,9 +71,13 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
private DocumentEvent myIsInUpdate;
private class MyRangeMarker extends RangeMarkerImpl {
private VisualPosition myStartPosition;
private VisualPosition myEndPosition;
private boolean myEndPositionIsLead;
private boolean myIsReleased;
private MyRangeMarker(DocumentEx document, int start, int end) {
MyRangeMarker(DocumentEx document, int start, int end) {
super(document, start, end);
myIsReleased = false;
}
@@ -81,6 +86,34 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
myIsReleased = true;
}
@Nullable
public VisualPosition getStartPosition() {
invalidateVisualPositions();
return myStartPosition;
}
public void setStartPosition(@NotNull VisualPosition startPosition) {
myStartPosition = startPosition;
}
@Nullable
public VisualPosition getEndPosition() {
invalidateVisualPositions();
return myEndPosition;
}
public void setEndPosition(@NotNull VisualPosition endPosition) {
myEndPosition = endPosition;
}
public boolean isEndPositionIsLead() {
return myEndPositionIsLead;
}
public void setEndPositionIsLead(boolean endPositionIsLead) {
myEndPositionIsLead = endPositionIsLead;
}
@Override
protected void changedUpdateImpl(DocumentEvent e) {
if (myIsReleased) return;
@@ -103,6 +136,16 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
protected void registerInDocument() {
}
private void invalidateVisualPositions() {
SoftWrapModelImpl model = myEditor.getSoftWrapModel();
if ((!myEditor.offsetToVisualPosition(myStart).equals(myStartPosition) && model.getSoftWrap(myStart) == null)
|| (!myEditor.offsetToVisualPosition(myEnd).equals(myEndPosition) && model.getSoftWrap(myEnd) == null))
{
myStartPosition = null;
myEndPosition = null;
}
}
}
public void beforeDocumentChange(DocumentEvent event) {
@@ -138,6 +181,23 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
return myEditor.getCaretModel().getOffset();
}
@NotNull
@Override
public VisualPosition getSelectionStartPosition() {
VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionStart());
if (!hasSelection()) {
return defaultPosition;
}
MyRangeMarker marker = mySelectionMarker.get();
if (marker == null) {
return defaultPosition;
}
VisualPosition result = marker.getStartPosition();
return result == null ? defaultPosition : result;
}
private void validateContext(boolean isWrite) {
if (isWrite) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -162,6 +222,23 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
return myEditor.getCaretModel().getOffset();
}
@NotNull
@Override
public VisualPosition getSelectionEndPosition() {
VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionEnd());
if (!hasSelection()) {
return defaultPosition;
}
MyRangeMarker marker = mySelectionMarker.get();
if (marker == null) {
return defaultPosition;
}
VisualPosition result = marker.getEndPosition();
return result == null ? defaultPosition : result;
}
public boolean hasSelection() {
validateContext(false);
MyRangeMarker marker = mySelectionMarker.get();
@@ -173,6 +250,17 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
}
public void setSelection(int startOffset, int endOffset) {
doSetSelection(myEditor.offsetToVisualPosition(startOffset), startOffset, myEditor.offsetToVisualPosition(endOffset), endOffset, false);
}
@Override
public void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset) {
doSetSelection(startPosition, startOffset, endPosition, endOffset, true);
}
private void doSetSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition,
int endOffset, boolean visualPositionAware)
{
validateContext(true);
removeBlockSelection();
@@ -186,7 +274,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
}
myLastSelectionStart = startOffset;
if (startOffset == endOffset) {
if (!visualPositionAware && startOffset == endOffset) {
removeSelection();
return;
}
@@ -204,7 +292,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
if (hasSelection()) {
oldSelectionStart = getSelectionStart();
oldSelectionEnd = getSelectionEnd();
if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset) return;
if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset && !visualPositionAware) return;
}
else {
oldSelectionStart = oldSelectionEnd = myEditor.getCaretModel().getOffset();
@@ -215,7 +303,20 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
marker.release();
}
mySelectionMarker.set(new MyRangeMarker((DocumentEx)doc, startOffset, endOffset));
marker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset);
if (visualPositionAware) {
if (endPosition.after(startPosition)) {
marker.setStartPosition(startPosition);
marker.setEndPosition(endPosition);
marker.setEndPositionIsLead(false);
}
else {
marker.setStartPosition(endPosition);
marker.setEndPosition(startPosition);
marker.setEndPositionIsLead(true);
}
}
mySelectionMarker.set(marker);
fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset);
@@ -432,7 +533,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
int selectionEnd = getSelectionEnd();
return text.subSequence(selectionStart, selectionEnd).toString();
}
private static void appendCharSequence(@NotNull StringBuffer buf, @NotNull CharSequence s, int srcOffset, int len) {
if (srcOffset < 0 || len < 0 || srcOffset > s.length() - len) {
throw new IndexOutOfBoundsException("srcOffset " + srcOffset + ", len " + len + ", s.length() " + s.length());
@@ -446,7 +547,6 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
}
}
public int getLeadSelectionOffset() {
validateContext(false);
int caretOffset = myEditor.getCaretModel().getOffset();
@@ -466,6 +566,24 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
return caretOffset;
}
@NotNull
@Override
public VisualPosition getLeadSelectionPosition() {
MyRangeMarker marker = mySelectionMarker.get();
VisualPosition caretPosition = myEditor.getCaretModel().getVisualPosition();
if (marker == null) {
return caretPosition;
}
VisualPosition startPosition = marker.getStartPosition();
VisualPosition endPosition = marker.getEndPosition();
if (startPosition == null || endPosition == null) {
return caretPosition;
}
return marker.isEndPositionIsLead() ? endPosition : startPosition;
}
public void selectLineAtCaret() {
validateContext(true);
int lineNumber = myEditor.getCaretModel().getLogicalPosition().line;
@@ -20,10 +20,11 @@ import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.event.SelectionListener;
import com.intellij.openapi.editor.markup.TextAttributes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,10 +46,22 @@ public class TextComponentSelectionModel implements SelectionModel {
return myTextComponent.getSelectionStart();
}
@Nullable
@Override
public VisualPosition getSelectionStartPosition() {
return null;
}
public int getSelectionEnd() {
return myTextComponent.getSelectionEnd();
}
@Nullable
@Override
public VisualPosition getSelectionEndPosition() {
return null;
}
@Nullable
public String getSelectedText() {
return myTextComponent.getSelectedText();
@@ -61,6 +74,12 @@ public class TextComponentSelectionModel implements SelectionModel {
return caretPosition == start ? end : start;
}
@Nullable
@Override
public VisualPosition getLeadSelectionPosition() {
return null;
}
public boolean hasSelection() {
return myTextComponent.getSelectionStart() != myTextComponent.getSelectionEnd();
}
@@ -76,6 +95,11 @@ public class TextComponentSelectionModel implements SelectionModel {
}
}
@Override
public void setSelection(@NotNull VisualPosition startPosition, int startOffset, @NotNull VisualPosition endPosition, int endOffset) {
setSelection(startOffset, endOffset);
}
public void removeSelection() {
final int position = myTextComponent.getCaretPosition();
myTextComponent.select(position, position);
@@ -33,7 +33,7 @@ import java.util.Set;
public interface EditorCustomization {
enum Feature {
SOFT_WRAP, SPELL_CHECK, NO_HORIZONTAL_SCROLLBAR
SOFT_WRAP, SPELL_CHECK, NO_HORIZONTAL_SCROLLBAR, ONE_LINE
}
ExtensionPointName<EditorCustomization> EP_NAME = ExtensionPointName.create("com.intellij.editorCustomization");
@@ -30,7 +30,7 @@ public interface EditorTextFieldProvider {
/**
* @param project target project
* @param features features to use within the returned editor text field
* @return {@link EditorTextField} with spell checking support.
* @return Multiline {@link EditorTextField} with spell checking support.
*/
EditorTextField getEditorField(@NotNull Language language, @NotNull Project project, @NotNull EditorCustomization.Feature ... features);
}
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2010 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.ui;
import com.intellij.openapi.editor.ex.EditorEx;
import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
import java.util.Set;
/**
* @author Kirill Likhodedov
*/
public class OneLineEditorCustomization implements EditorCustomization {
public Set<Feature> getSupportedFeatures() {
return EnumSet.of(Feature.ONE_LINE);
}
public void customize(@NotNull EditorEx editor, @NotNull Feature feature) {
if (Feature.ONE_LINE.equals(feature)) {
editor.setOneLineMode(true);
}
}
}
@@ -454,6 +454,7 @@
<editorOptionsProvider instance="com.intellij.application.options.editor.EditorAppearanceConfigurable"/>
<editorCustomization implementation="com.intellij.ui.SoftWrapsEditorCustomization"/>
<editorCustomization implementation="com.intellij.ui.HorizontalScrollBarEditorCustomization"/>
<editorCustomization implementation="com.intellij.ui.OneLineEditorCustomization"/>
<!-- Colors & Fonts-->
<editorOptionsProvider implementation="com.intellij.application.options.colors.ColorAndFontOptions"/>
<editorOptionsProvider instance="com.intellij.application.options.editor.EditorTabsConfigurable"/>
@@ -333,6 +333,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
PsiFile addFileToProject(@NonNls String relativePath, @NonNls String fileText);
@Nullable
List<String> getCompletionVariants(String... filesBefore);
/**
@@ -29,6 +29,7 @@ import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.codeInsight.template.impl.actions.ListTemplatesAction;
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataContext;
@@ -152,27 +153,33 @@ public class CodeInsightTestUtil {
}
public static void doInlineRename(VariableInplaceRenameHandler handler, final String newName, CodeInsightTestFixture fixture) {
final Editor editor = fixture.getEditor();
PsiElement element = fixture.getElementAtCaret();
doInlineRename(handler, newName, fixture.getEditor(), fixture.getElementAtCaret());
}
public static void doInlineRename(VariableInplaceRenameHandler handler, final String newName, Editor editor, PsiElement elementAtCaret) {
Project project = editor.getProject();
TemplateManagerImpl templateManager = (TemplateManagerImpl)TemplateManager.getInstance(project);
try {
templateManager.setTemplateTesting(true);
VariableInplaceRenamer renamer = handler.doRename(element, editor, null);
VariableInplaceRenamer renamer = handler.doRename(elementAtCaret, editor, null);
if (editor instanceof EditorWindow) {
editor = ((EditorWindow)editor).getDelegate();
}
TemplateState state = TemplateManagerImpl.getTemplateState(editor);
final TextRange range = state.getCurrentVariableRange();
assert range != null;
final Editor finalEditor = editor;
new WriteCommandAction.Simple(project) {
@Override
protected void run() throws Throwable {
editor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), newName);
finalEditor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), newName);
}
}.execute().throwException();
assert renamer != null;
renamer.finish();
TemplateManagerImpl.getTemplateState(editor).gotoEnd();
renamer.performAutomaticRename(newName, element);
renamer.performAutomaticRename(newName, elementAtCaret);
}
finally {
templateManager.setTemplateTesting(false);
@@ -498,10 +498,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
public void testCompletion(final String[] filesBefore, final String fileAfter) {
assertInitialized();
configureByFiles(filesBefore);
final LookupElement[] items = complete(CompletionType.BASIC);
if (items != null) {
System.out.println("items = " + Arrays.toString(items));
}
complete(CompletionType.BASIC);
checkResultByFile(fileAfter);
}
@@ -518,6 +515,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
public void testCompletionVariants(final String fileBefore, final String... expectedItems) {
assertInitialized();
final List<String> result = getCompletionVariants(fileBefore);
UsefulTestCase.assertNotNull(result);
UsefulTestCase.assertSameElements(result, expectedItems);
}
@@ -62,21 +62,21 @@ public class VirtualFileHolder implements FileHolder {
for(FilePath dirtyFile: dirtyFiles) {
VirtualFile f = dirtyFile.getVirtualFile();
if (f != null) {
files.remove(f);
if (f.isDirectory()) ++ result;
if (files.remove(f)) {
if (f.isDirectory()) ++ result;
}
}
else {
cleanDroppedFiles = true;
}
if (cleanDroppedFiles) {
for (Iterator<VirtualFile> iterator = files.iterator(); iterator.hasNext();) {
final VirtualFile file = iterator.next();
if (fileDropped(file)) {
iterator.remove();
scope.addDirtyFile(new FilePathImpl(file));
if (file.isDirectory()) ++ result;
}
}
if (cleanDroppedFiles) {
for (Iterator<VirtualFile> iterator = files.iterator(); iterator.hasNext();) {
final VirtualFile file = iterator.next();
if (fileDropped(file)) {
iterator.remove();
scope.addDirtyFile(new FilePathImpl(file));
if (file.isDirectory()) ++ result;
}
}
}
@@ -156,6 +156,7 @@ public class VirtualFileHolder implements FileHolder {
}
public int getNumDirs() {
assert myNumDirs >= 0;
return myNumDirs;
}
}
@@ -175,6 +175,7 @@ public abstract class NewEditChangelistPanel extends JPanel {
final EnumSet<EditorCustomization.Feature> features = EnumSet.of(EditorCustomization.Feature.SPELL_CHECK);
if (defaultLines == 1) {
features.add(EditorCustomization.Feature.NO_HORIZONTAL_SCROLLBAR);
features.add(EditorCustomization.Feature.ONE_LINE);
} else {
features.add(EditorCustomization.Feature.SOFT_WRAP);
}
@@ -246,7 +246,8 @@ public class TableSorter extends AbstractTableModel {
}
private Row[] getViewToModel() {
if (viewToModel == null) {
if (viewToModel == null ||
viewToModel.length != tableModel.getRowCount()) {
final int tableModelRowCount = tableModel.getRowCount();
viewToModel = new Row[tableModelRowCount];
for (int row = 0; row < tableModelRowCount; row++) {
@@ -27,6 +27,9 @@ import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
@@ -55,22 +58,7 @@ public class AndroidFacetType extends FacetType<AndroidFacet, AndroidFacetConfig
public AndroidFacetConfiguration createDefaultConfiguration() {
AndroidFacetConfiguration configuration = new AndroidFacetConfiguration();
PropertiesComponent component = PropertiesComponent.getInstance();
LibraryTable libraryTable = LibraryTablesRegistrar.getInstance().getLibraryTable();
if (component.isValueSet(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY)) {
Library defaultLib = libraryTable.getLibraryByName(component.getValue(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY));
if (defaultLib != null && tryToSetAndroidPlatform(configuration, defaultLib)) {
return configuration;
}
for (Library library : libraryTable.getLibraries()) {
if (tryToSetAndroidPlatform(configuration, library)) {
component.setValue(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY, library.getName());
return configuration;
}
}
}
return configuration;
return new AndroidFacetConfiguration();
}
private static boolean tryToSetAndroidPlatform(AndroidFacetConfiguration configuration, Library library) {
@@ -86,9 +74,40 @@ public class AndroidFacetType extends FacetType<AndroidFacet, AndroidFacetConfig
String name,
@NotNull AndroidFacetConfiguration configuration,
@Nullable Facet underlyingFacet) {
setupPlatform(module, configuration);
return new AndroidFacet(module, name, configuration);
}
private static void setupPlatform(@NotNull Module module, @NotNull AndroidFacetConfiguration configuration) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
if (entry instanceof LibraryOrderEntry) {
LibraryOrderEntry libEntry = (LibraryOrderEntry)entry;
Library library = libEntry.getLibrary();
if (library != null &&
LibraryTablesRegistrar.APPLICATION_LEVEL.equals(libEntry.getLibraryLevel()) &&
tryToSetAndroidPlatform(configuration, library)) {
return;
}
}
}
PropertiesComponent component = PropertiesComponent.getInstance();
LibraryTable libraryTable = LibraryTablesRegistrar.getInstance().getLibraryTable();
if (component.isValueSet(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY)) {
Library defaultLib = libraryTable.getLibraryByName(component.getValue(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY));
if (defaultLib != null && tryToSetAndroidPlatform(configuration, defaultLib)) {
return;
}
for (Library library : libraryTable.getLibraries()) {
if (tryToSetAndroidPlatform(configuration, library)) {
component.setValue(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY, library.getName());
return;
}
}
}
}
public boolean isSuitableModuleType(ModuleType moduleType) {
return moduleType instanceof JavaModuleType || moduleType instanceof AndroidModuleType;
}
@@ -255,7 +255,7 @@ public class DeviceChooser extends DialogWrapper implements AndroidDebugBridge.I
chooser.show();
avd = chooser.getSelectedAvd();
if (chooser.getExitCode() != OK_EXIT_CODE) return;
assert avd != null;
if (avd == null) return;
}
myFacet.launchEmulator(avd != null ? avd.getName() : null, "", null);
}
@@ -43,11 +43,7 @@ import git4idea.GitUtil;
import git4idea.GitVcs;
import git4idea.actions.GitRepositoryAction;
import git4idea.actions.GitShowAllSubmittedFilesAction;
import git4idea.commands.GitCommand;
import git4idea.commands.GitHandlerUtil;
import git4idea.commands.GitLineHandler;
import git4idea.commands.GitSimpleHandler;
import git4idea.commands.StringScanner;
import git4idea.commands.*;
import git4idea.config.GitVcsSettings;
import git4idea.i18n.GitBundle;
import git4idea.ui.GitUIUtil;
@@ -55,11 +51,7 @@ import git4idea.update.UpdatePolicyUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTree;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
@@ -67,18 +59,11 @@ import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.Color;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -184,6 +169,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
setTitle(GitBundle.getString("push.active.title"));
setOKButtonText(GitBundle.getString("push.active.rebase.and.push"));
setCancelButtonText(GitBundle.getString("git.push.active.close"));
init();
}
@@ -494,6 +494,8 @@ git.executable.dialog.error=It doesn't appear to be a valid git executable
git.executable.filechooser.title=Git executable
git.executable.filechooser.description=Specify the full path to git executable
git.push.active.close=Close
git.unstash.clear.confirmation.message=Remove all stashes? This cannot be undone.
git.unstash.clear.confirmation.title=Remove all stashes?
git.unstash.drop.confirmation.message=<html>Do you want to remove {0}?<br/>"{1}"</html>
@@ -17,7 +17,6 @@
package com.intellij.tasks.actions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskManager;
@@ -34,34 +33,9 @@ public class TaskSearchSupport {
protected NameUtil.Matcher myMatcher;
private final TaskManagerImpl myManager;
private final Project myProject;
private final Comparator<Task> myTaskComparator;
private final boolean myRemoveLocal;
public TaskSearchSupport(final Project project, boolean removeLocal) {
myProject = project;
myRemoveLocal = removeLocal;
myManager = (TaskManagerImpl)TaskManager.getManager(myProject);
myTaskComparator = new Comparator<Task>() {
public int compare(Task o1, Task o2) {
int i = Comparing.compare(isOpen(o2, myProject), isOpen(o1, myProject));
if (i != 0) {
return i;
}
//i = Comparing.compare(o1.isClosed(), o2.isClosed());
//if (i != 0) {
// return i;
//}
i = Comparing.compare(o2.getUpdated(), o1.getUpdated());
return i == 0 ? Comparing.compare(o2.getCreated(), o1.getCreated()) : i;
}
};
}
private static boolean isOpen(Task task, Project project) {
return !task.isClosed() && !TaskManager.getManager(project).getOpenChangelists(task).isEmpty();
public TaskSearchSupport(final Project project) {
myManager = (TaskManagerImpl)TaskManager.getManager(project);
}
public List<Task> getItems(String pattern, boolean cached) {
@@ -90,15 +64,6 @@ public class TaskSearchSupport {
}
private List<Task> getTasks(String pattern, boolean cached) {
Set<Task> taskSet = new HashSet<Task>(myManager.getCachedIssues());
if (!cached) {
taskSet.addAll(myManager.getIssues(pattern));
}
if (myRemoveLocal) {
taskSet.removeAll(Arrays.asList(myManager.getLocalTasks()));
}
List<Task> issues = new ArrayList<Task>(taskSet);
Collections.sort(issues, myTaskComparator);
return issues;
return cached ? myManager.getCachedIssues() : myManager.getIssues(pattern);
}
}
@@ -15,8 +15,6 @@ import com.intellij.psi.PsiFile;
import com.intellij.tasks.Task;
import com.intellij.tasks.actions.TaskSearchSupport;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import java.util.List;
import java.util.concurrent.Callable;
@@ -55,9 +53,9 @@ public class TaskCompletionContributor extends CompletionContributor {
}
result = result.withPrefixMatcher(new PlainPrefixMatcher(prefix));
final TaskSearchSupport searchSupport = new TaskSearchSupport(file.getProject(), false);
final TaskSearchSupport searchSupport = new TaskSearchSupport(file.getProject());
List<Task> items = searchSupport.getItems(prefix, true);
addCompletionElements(result, consumer, items);
addCompletionElements(result, consumer, items, -10000);
Future<List<Task>> future = ApplicationManager.getApplication().executeOnPooledThread(new Callable<List<Task>>() {
@Override
@@ -70,7 +68,7 @@ public class TaskCompletionContributor extends CompletionContributor {
try {
List<Task> tasks = future.get(100, TimeUnit.MILLISECONDS);
if (tasks != null) {
addCompletionElements(result, consumer, tasks);
addCompletionElements(result, consumer, tasks, 0);
return;
}
}
@@ -85,32 +83,31 @@ public class TaskCompletionContributor extends CompletionContributor {
}
}
private static void addCompletionElements(CompletionResultSet result, final Consumer<Task> consumer, List<Task> items) {
private static void addCompletionElements(CompletionResultSet result, final Consumer<Task> consumer, List<Task> items, int index) {
final AutoCompletionPolicy completionPolicy = ApplicationManager.getApplication().isUnitTestMode()
? AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE
: AutoCompletionPolicy.NEVER_AUTOCOMPLETE;
result.addAllElements(ContainerUtil.map(items, new Function<Task, LookupElement>() {
@Override
public LookupElement fun(final Task task) {
LookupElementBuilder builder = LookupElementBuilder.create(task.getId())
.setIcon(task.getIcon())
.addLookupString(task.getSummary())
.setTailText(" " + task.getSummary(), true)
.setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
Document document = context.getEditor().getDocument();
String s = task.getId() + ": " + task.getSummary();
document.replaceString(context.getStartOffset(), context.getTailOffset(), s);
context.getEditor().getCaretModel().moveToOffset(context.getStartOffset() + s.length());
consumer.consume(task);
}
});
if (task.isClosed()) {
builder = builder.setStrikeout();
}
return builder.withAutoCompletionPolicy(completionPolicy);
for (final Task task : items) {
LookupElementBuilder builder = LookupElementBuilder.create(task.getId())
.setIcon(task.getIcon())
.addLookupString(task.getSummary())
.setTailText(" " + task.getSummary(), true)
.setInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
Document document = context.getEditor().getDocument();
String s = task.getId() + ": " + task.getSummary();
document.replaceString(context.getStartOffset(), context.getTailOffset(), s);
context.getEditor().getCaretModel().moveToOffset(context.getStartOffset() + s.length());
consumer.consume(task);
}
});
if (task.isClosed()) {
builder = builder.setStrikeout();
}
}));
result.addElement(PrioritizedLookupElement.withGrouping(builder.withAutoCompletionPolicy(completionPolicy), index--));
}
}
}
@@ -35,6 +35,13 @@ public class TaskCompletionTest extends LightCodeInsightFixtureTestCase {
assertEquals(2, elements.length);
}
public void testKeepOrder() throws Exception {
configureFile("<caret>");
configureRepository(new LocalTaskImpl("TEST-002", "Test task 2"), new LocalTaskImpl("TEST-001", "Test task 1"));
myFixture.complete(CompletionType.BASIC);
assertEquals(Arrays.asList("TEST-002", "TEST-001"), myFixture.getLookupElementStrings());
}
public void testSIOOBE() throws Exception {
doTest(" <caret> my", " TEST-001: Test task my");
}
@@ -24,6 +24,8 @@ import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.impl.schema.TypeDescriptor;
import com.intellij.xml.impl.schema.XmlNSTypeDescriptorProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,7 +35,7 @@ import java.util.Map;
/**
* @author Maxim.Mossienko
*/
public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware {
public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware, XmlNSTypeDescriptorProvider {
private XmlNSDescriptor myDelegate;
private boolean myRelaxed;
private boolean myCaseSensitive;
@@ -126,4 +128,16 @@ public class HtmlNSDescriptorImpl implements XmlNSDescriptor, DumbAware {
public Object[] getDependences() {
return myDelegate == null ? null : myDelegate.getDependences();
}
@Override
public TypeDescriptor getTypeDescriptor(String name, XmlTag context) {
return myDelegate instanceof XmlNSTypeDescriptorProvider ?
((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(name, context) : null;
}
@Override
public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
return myDelegate instanceof XmlNSTypeDescriptorProvider ?
((XmlNSTypeDescriptorProvider)myDelegate).getTypeDescriptor(descriptorTag) : null;
}
}