mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -426,14 +426,4 @@ public class JVMNameUtil {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static PsiClass getTopLevelParentClass(PsiClass psiClass) {
|
||||
PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
|
||||
while (enclosing != null) {
|
||||
psiClass = enclosing;
|
||||
enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
|
||||
}
|
||||
return psiClass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public class PositionManagerImpl implements PositionManager {
|
||||
}
|
||||
|
||||
if (PsiUtil.isLocalOrAnonymousClass(psiClass)) {
|
||||
PsiClass parent = JVMNameUtil.getTopLevelParentClass(psiClass);
|
||||
PsiClass parent = TopLevelParentClassProvider.getTopLevelParentClass(psiClass);
|
||||
|
||||
if (parent == null) {
|
||||
return;
|
||||
@@ -244,7 +244,7 @@ public class PositionManagerImpl implements PositionManager {
|
||||
}
|
||||
|
||||
if(PsiUtil.isLocalOrAnonymousClass(psiClass)) {
|
||||
final PsiClass parentNonLocal = JVMNameUtil.getTopLevelParentClass(psiClass);
|
||||
final PsiClass parentNonLocal = TopLevelParentClassProvider.getTopLevelParentClass(psiClass);
|
||||
if(parentNonLocal == null) {
|
||||
LOG.error("Local or anonymous class has no non-local parent");
|
||||
return null;
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.debugger.engine;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public abstract class TopLevelParentClassProvider {
|
||||
private static final ExtensionPointName<TopLevelParentClassProvider> EP_NAME =
|
||||
ExtensionPointName.create("com.intellij.topLevelClassProvider");
|
||||
|
||||
public static PsiClass getTopLevelParentClass(PsiClass psiClass) {
|
||||
for (TopLevelParentClassProvider provider : EP_NAME.getExtensions()) {
|
||||
final PsiClass custom = provider.getCustomTopLevelParentClass(psiClass);
|
||||
if (custom != null) return custom;
|
||||
}
|
||||
|
||||
PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
|
||||
while (enclosing != null) {
|
||||
psiClass = enclosing;
|
||||
enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
|
||||
}
|
||||
return psiClass;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract PsiClass getCustomTopLevelParentClass(PsiClass psiClass);
|
||||
|
||||
}
|
||||
+11
-5
@@ -98,7 +98,7 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
|
||||
numberOfSymbolsToCopy = Math.min(escapedEndOffset, fileEndOffset) - Math.max(fileStartOffset, escapedStartOffset);
|
||||
if (numberOfSymbolsToCopy > 0) {
|
||||
textWasChanged = true;
|
||||
buffer.append(unescapeStringCharacters(text.substring(givenTextStartOffset, givenTextStartOffset + numberOfSymbolsToCopy)));
|
||||
buffer.append(unescape(text.substring(givenTextStartOffset, givenTextStartOffset + numberOfSymbolsToCopy), element));
|
||||
givenTextStartOffset += numberOfSymbolsToCopy;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,12 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
|
||||
}
|
||||
return textWasChanged ? buffer.toString() : null;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
protected String unescape(String text, PsiElement token) {
|
||||
return unescapeStringCharacters(text);
|
||||
}
|
||||
|
||||
public String preprocessOnPaste(final Project project, final PsiFile file, final Editor editor, String text, final RawText rawText) {
|
||||
final Document document = editor.getDocument();
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
@@ -139,9 +144,10 @@ public class StringLiteralCopyPasteProcessor implements CopyPastePreProcessor {
|
||||
@NonNls String breaker = getLineBreaker(token);
|
||||
final String[] lines = LineTokenizer.tokenize(text.toCharArray(), false, true);
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
buffer.append(escapeCharCharacters(line, token, escapeSlashes));
|
||||
if (i != lines.length - 1) buffer.append(breaker);
|
||||
buffer.append(escapeCharCharacters(lines[i], token, escapeSlashes));
|
||||
if (i != lines.length - 1 || "\n".equals(breaker) && text.endsWith("\n")) {
|
||||
buffer.append(breaker);
|
||||
}
|
||||
}
|
||||
text = buffer.toString();
|
||||
}
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
package com.intellij.ide.util;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -102,4 +107,51 @@ public class SuperMethodWarningUtil {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void checkSuperMethod(final PsiMethod method,
|
||||
final String actionString,
|
||||
final PsiElementProcessor<PsiMethod> processor,
|
||||
final Editor editor) {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass == null) {
|
||||
processor.execute(method);
|
||||
return;
|
||||
}
|
||||
|
||||
PsiMethod superMethod = method.findDeepestSuperMethod();
|
||||
if (superMethod == null) {
|
||||
processor.execute(method);
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiClass containingClass = superMethod.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
processor.execute(method);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
processor.execute(superMethod);
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiMethod[] methods = new PsiMethod[]{superMethod, method};
|
||||
final String renameBase = actionString + " base method";
|
||||
final String renameCurrent = actionString + " only current method";
|
||||
final JBList list = new JBList(renameBase, renameCurrent);
|
||||
JBPopupFactory.getInstance().createListPopupBuilder(list)
|
||||
.setTitle(method.getName() + (containingClass.isInterface() && !aClass.isInterface() ? " implements" : " overrides") + " method of " +
|
||||
SymbolPresentationUtil.getSymbolPresentableText(containingClass))
|
||||
.setMovable(false)
|
||||
.setResizable(false)
|
||||
.setRequestFocus(true)
|
||||
.setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
final Object value = list.getSelectedValue();
|
||||
if (value instanceof String) {
|
||||
processor.execute(methods[value.equals(renameBase) ? 0 : 1]);
|
||||
}
|
||||
}
|
||||
}).createPopup().showInBestPositionFor(editor);
|
||||
}
|
||||
}
|
||||
@@ -65,9 +65,6 @@ public class JavaRefactoringSupportProvider extends RefactoringSupportProvider {
|
||||
|
||||
@Override
|
||||
public boolean isMemberInplaceRenameAvailable(PsiElement elementToRename, PsiElement context) {
|
||||
if (elementToRename instanceof PsiMethod && ((PsiMethod)elementToRename).findDeepestSuperMethods().length > 0) {
|
||||
return false;
|
||||
}
|
||||
return elementToRename instanceof PsiMember;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.psi.impl.light;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LightField extends LightElement implements PsiField {
|
||||
private final PsiField myField;
|
||||
private final PsiClass myContainingClass;
|
||||
|
||||
public LightField(@NotNull final PsiManager manager, @NotNull final PsiField field, @NotNull final PsiClass containingClass) {
|
||||
super(manager, JavaLanguage.INSTANCE);
|
||||
myField = field;
|
||||
myContainingClass = containingClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitializer(@Nullable final PsiExpression initializer) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Not supported");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SearchScope getUseScope() {
|
||||
return myField.getUseScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return myField.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiIdentifier getNameIdentifier() {
|
||||
return myField.getNameIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiDocComment getDocComment() {
|
||||
return myField.getDocComment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
return myField.isDeprecated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getContainingClass() {
|
||||
return myContainingClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return myField.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeElement getTypeElement() {
|
||||
return myField.getTypeElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiExpression getInitializer() {
|
||||
return myField.getInitializer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInitializer() {
|
||||
return myField.hasInitializer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void normalizeDeclaration() throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object computeConstantValue() {
|
||||
return myField.computeConstantValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NonNls @NotNull final String name) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getTypeNoResolve() {
|
||||
return myField.getTypeNoResolve();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
return myField.getModifierList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@Modifier @NonNls @NotNull final String name) {
|
||||
return myField.hasModifierProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return myField.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement copy() {
|
||||
return new LightField(myManager, (PsiField)myField.copy(), myContainingClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextRange getTextRange() {
|
||||
return new TextRange(-1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myContainingClass.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PsiField:" + getName();
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,10 @@ package com.intellij.refactoring.rename;
|
||||
import com.intellij.ide.util.SuperMethodWarningUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
@@ -237,6 +239,25 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor {
|
||||
return SuperMethodWarningUtil.checkSuperMethod(psiMethod, RefactoringBundle.message("to.rename"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void substituteElementToRename(@NotNull PsiElement element,
|
||||
@NotNull Editor editor,
|
||||
@NotNull final Pass<PsiElement> renameCallback) {
|
||||
PsiMethod psiMethod = (PsiMethod)element;
|
||||
if (psiMethod.isConstructor()) {
|
||||
super.substituteElementToRename(element, editor, renameCallback);
|
||||
}
|
||||
else {
|
||||
SuperMethodWarningUtil.checkSuperMethod(psiMethod, "Rename", new PsiElementProcessor<PsiMethod>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiMethod method) {
|
||||
renameCallback.pass(method);
|
||||
return false;
|
||||
}
|
||||
}, editor);
|
||||
}
|
||||
}
|
||||
|
||||
private static void findSubmemberHidesMemberCollisions(final PsiMethod method, final String newName, final List<UsageInfo> result) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -14,22 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.psi.impl.java.stubs;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.impl.cache.TypeInfo;
|
||||
import com.intellij.psi.stubs.NamedStub;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public interface PsiMethodStub extends NamedStub<PsiMethod> {
|
||||
boolean isConstructor();
|
||||
boolean isVarArgs();
|
||||
boolean isAnnotationMethod();
|
||||
|
||||
String getDefaultValueText();
|
||||
@Nullable String getDefaultValueText();
|
||||
@NotNull TypeInfo getReturnTypeText(boolean doResolve);
|
||||
|
||||
boolean isDeprecated();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -174,8 +174,9 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
|
||||
|
||||
builder.append(getName()).append(":").append(TypeInfo.createTypeText(getReturnTypeText(false)));
|
||||
|
||||
if (getDefaultValueText() != null) {
|
||||
builder.append(" default=").append(getDefaultValueText());
|
||||
final String defaultValue = getDefaultValueText();
|
||||
if (defaultValue != null) {
|
||||
builder.append(" default=").append(defaultValue);
|
||||
}
|
||||
|
||||
builder.append("]");
|
||||
|
||||
@@ -41,10 +41,6 @@ public class LightMethod extends LightElement implements PsiMethod {
|
||||
private final PsiMethod myMethod;
|
||||
private final PsiClass myContainingClass;
|
||||
|
||||
public LightMethod(PsiMethod method, PsiClass containingClass) {
|
||||
this(method.getManager(), method, containingClass);
|
||||
}
|
||||
|
||||
public LightMethod(PsiManager manager, PsiMethod method, PsiClass containingClass) {
|
||||
super(manager, JavaLanguage.INSTANCE);
|
||||
myMethod = method;
|
||||
|
||||
@@ -60,6 +60,22 @@ class Foo { List a; Map b; }
|
||||
assertEquals 0, foldRegion.startOffset
|
||||
assertEquals text.indexOf("import") - 1, foldRegion.endOffset
|
||||
}
|
||||
|
||||
public void testSubsequentCollapseBlock() {
|
||||
def text = """\
|
||||
class Test {
|
||||
void test(int i) {
|
||||
if (i > 1) {
|
||||
<caret>i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
configure text
|
||||
myFixture.performEditorAction 'CollapseBlock'
|
||||
myFixture.performEditorAction 'CollapseBlock'
|
||||
assertEquals(text.indexOf('}', text.indexOf('i++')), myFixture.editor.caretModel.offset)
|
||||
}
|
||||
|
||||
private def configure(String text) {
|
||||
myFixture.configureByText("a.java", text)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.ex;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public interface DisposableIterator<T> extends Iterator<T> {
|
||||
void dispose();
|
||||
DisposableIterator EMPTY = new DisposableIterator() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalAccessError();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.ex.DisposableIterator;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -22,14 +23,12 @@ import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.WalkingState;
|
||||
import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.TLongHashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -495,15 +494,18 @@ public abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBla
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Iterator<T> overlappingIterator(final int startOffset, final int endOffset) {
|
||||
DisposableIterator<T> overlappingIterator(final int startOffset, final int endOffset) {
|
||||
final IntervalNode<T> firstOverlap = findMinOverlappingWith(getRoot(), new TextRangeInterval(startOffset, endOffset), modCount, 0);
|
||||
if (firstOverlap == null) {
|
||||
return ContainerUtil.emptyIterator();
|
||||
return DisposableIterator.EMPTY;
|
||||
}
|
||||
final int firstOverlapDelta = firstOverlap.computeDeltaUpToRoot();
|
||||
final int firstOverlapStart = firstOverlap.intervalStart() + firstOverlapDelta;
|
||||
final int modCountBefore = modCount;
|
||||
return new Iterator<T>() {
|
||||
|
||||
l.readLock().lock();
|
||||
|
||||
return new DisposableIterator<T>() {
|
||||
private IntervalNode<T> currentNode = firstOverlap;
|
||||
private int deltaUpToRootExclusive = firstOverlapDelta-firstOverlap.delta;
|
||||
private int indexInCurrentList = 0;
|
||||
@@ -513,39 +515,33 @@ public abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBla
|
||||
public boolean hasNext() {
|
||||
if (current != null) return true;
|
||||
if (currentNode == null) return false;
|
||||
try {
|
||||
l.readLock().lock();
|
||||
|
||||
if (modCount != modCountBefore) throw new ConcurrentModificationException();
|
||||
while (indexInCurrentList != currentNode.intervals.size()) {
|
||||
T t = currentNode.intervals.get(indexInCurrentList++).get();
|
||||
if (t != null) {
|
||||
current = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
indexInCurrentList = 0;
|
||||
while (true) {
|
||||
currentNode = nextNode(currentNode);
|
||||
if (currentNode == null) {
|
||||
return false;
|
||||
}
|
||||
if (overlaps(currentNode, startOffset, endOffset, deltaUpToRootExclusive)) {
|
||||
assert currentNode.intervalStart() + deltaUpToRootExclusive + currentNode.delta >= firstOverlapStart;
|
||||
indexInCurrentList = 0;
|
||||
while (indexInCurrentList != currentNode.intervals.size()) {
|
||||
T t = currentNode.intervals.get(indexInCurrentList++).get();
|
||||
if (t != null) {
|
||||
current = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
indexInCurrentList = 0;
|
||||
}
|
||||
if (modCount != modCountBefore) throw new ConcurrentModificationException();
|
||||
while (indexInCurrentList != currentNode.intervals.size()) {
|
||||
T t = currentNode.intervals.get(indexInCurrentList++).get();
|
||||
if (t != null) {
|
||||
current = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
l.readLock().unlock();
|
||||
indexInCurrentList = 0;
|
||||
while (true) {
|
||||
currentNode = nextNode(currentNode);
|
||||
if (currentNode == null) {
|
||||
return false;
|
||||
}
|
||||
if (overlaps(currentNode, startOffset, endOffset, deltaUpToRootExclusive)) {
|
||||
assert currentNode.intervalStart() + deltaUpToRootExclusive + currentNode.delta >= firstOverlapStart;
|
||||
indexInCurrentList = 0;
|
||||
while (indexInCurrentList != currentNode.intervals.size()) {
|
||||
T t = currentNode.intervals.get(indexInCurrentList++).get();
|
||||
if (t != null) {
|
||||
current = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
indexInCurrentList = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,6 +558,11 @@ public abstract class IntervalTreeImpl<T extends MutableInterval> extends RedBla
|
||||
throw new IncorrectOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
l.readLock().unlock();
|
||||
}
|
||||
|
||||
// next node in in-order traversal
|
||||
private IntervalNode<T> nextNode(@NotNull IntervalNode<T> root) {
|
||||
assert root.isValid();
|
||||
|
||||
@@ -52,9 +52,13 @@ public abstract class PsiCachedValue<T> extends CachedValueBase<T> {
|
||||
|
||||
@Override
|
||||
protected boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) {
|
||||
return !(dependency instanceof PsiElement && myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount()) &&
|
||||
super.isDependencyOutOfDate(dependency, oldTimeStamp);
|
||||
if (dependency instanceof PsiElement &&
|
||||
myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount() &&
|
||||
((PsiElement)dependency).isPhysical()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.isDependencyOutOfDate(dependency, oldTimeStamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,11 +20,11 @@ package com.intellij.ide;
|
||||
*/
|
||||
public interface StandardTargetWeights {
|
||||
float PROJECT_WEIGHT = 1;
|
||||
float FAVORITES_WEIGHT = 1.01f;
|
||||
float PACKAGES_WEIGHT = 2;
|
||||
float J2EE_WEIGHT = 3;
|
||||
float STRUCTURE_WEIGHT = 4;
|
||||
float COMMANDER_WEIGHT = 5;
|
||||
float FAVORITES_WEIGHT = 6;
|
||||
float SCOPE_WEIGHT = 6.5f;
|
||||
float NAV_BAR_WEIGHT = 8;
|
||||
float CHANGES_VIEW = 9;
|
||||
|
||||
@@ -125,7 +125,6 @@ public class EnterHandler extends BaseEnterHandler {
|
||||
|
||||
if (result == EnterHandlerDelegate.Result.Stop) return;
|
||||
if (result != EnterHandlerDelegate.Result.Continue) {
|
||||
text = document.getCharsSequence();
|
||||
if (result == EnterHandlerDelegate.Result.DefaultForceIndent) {
|
||||
forceIndent = true;
|
||||
}
|
||||
@@ -133,6 +132,7 @@ public class EnterHandler extends BaseEnterHandler {
|
||||
}
|
||||
}
|
||||
|
||||
text = document.getCharsSequence(); // update after changes done in preprocessEnter()
|
||||
caretOffset = caretOffsetRef.get().intValue();
|
||||
boolean isFirstColumn = caretOffset == 0 || text.charAt(caretOffset - 1) == '\n';
|
||||
final boolean insertSpace =
|
||||
|
||||
@@ -409,6 +409,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L
|
||||
myConsole.print(fragment.getText(), consoleViewType);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
final LogFilterModel.MyProcessingResult processingResult = myModel.processLine(line);
|
||||
@@ -422,11 +423,12 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L
|
||||
myConsole.print(messagePrefix, type);
|
||||
}
|
||||
myConsole.print(line + "\n", type);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -180,9 +180,6 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
myPanel.removeAll();
|
||||
myPanel.add(myHistoryViewer.getComponent(), BorderLayout.CENTER);
|
||||
myFullEditor = fileManager.openTextEditor(new OpenFileDescriptor(getProject(), virtualFile, 0), true);
|
||||
configureFullEditor();
|
||||
setConsoleFilePinned(fileManager);
|
||||
|
||||
myHistoryViewer.setHorizontalScrollbarVisible(true);
|
||||
myCurrentEditor = myFullEditor;
|
||||
}
|
||||
@@ -201,7 +198,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
|
||||
public void setFullEditorActions(ActionGroup actionGroup) {
|
||||
myFullEditorActions = actionGroup;
|
||||
configureFullEditor();
|
||||
configureFullEditor(myFullEditor);
|
||||
}
|
||||
|
||||
public void setShowSeparatorLine(boolean showSeparatorLine) {
|
||||
@@ -539,6 +536,11 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
for (FileEditor fileEditor : source.getAllEditors(file)) {
|
||||
if (!(fileEditor instanceof TextEditor)) continue;
|
||||
final Editor editor = ((TextEditor)fileEditor).getEditor();
|
||||
// todo what if it is splitted?
|
||||
myCurrentEditor = editor;
|
||||
myFullEditor = editor;
|
||||
configureFullEditor(editor);
|
||||
setConsoleFilePinned((FileEditorManagerEx)source);
|
||||
EmptyAction.registerActionShortcuts(editor.getComponent(), myConsoleEditor.getComponent());
|
||||
editor.getCaretModel().addCaretListener(new CaretListener() {
|
||||
public void caretPositionChanged(CaretEvent e) {
|
||||
@@ -595,20 +597,18 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
|
||||
}
|
||||
editorManager.closeFile(file);
|
||||
myFullEditor = editorManager.openTextEditor(new OpenFileDescriptor(getProject(), newVFile, offset), focusEditor);
|
||||
configureFullEditor();
|
||||
setConsoleFilePinned(editorManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void configureFullEditor() {
|
||||
if (myFullEditor == null || myFullEditorActions == null) return;
|
||||
private void configureFullEditor(final Editor editor) {
|
||||
if (editor == null || myFullEditorActions == null) return;
|
||||
final JPanel header = new JPanel(new BorderLayout());
|
||||
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myFullEditorActions, true);
|
||||
actionToolbar.setTargetComponent(myFullEditor.getContentComponent());
|
||||
actionToolbar.setTargetComponent(editor.getContentComponent());
|
||||
header.add(actionToolbar.getComponent(), BorderLayout.EAST);
|
||||
myFullEditor.setHeaderComponent(header);
|
||||
myFullEditor.getSettings().setLineMarkerAreaShown(false);
|
||||
editor.setHeaderComponent(header);
|
||||
editor.getSettings().setLineMarkerAreaShown(false);
|
||||
}
|
||||
|
||||
public void setInputText(final String query) {
|
||||
|
||||
@@ -220,7 +220,8 @@ public class PsiCopyPasteManager {
|
||||
if (myElements == null || myElements.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return myElements [0].getProject();
|
||||
final PsiElement element = myElements[0];
|
||||
return element.isValid() ? element.getProject() : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -52,7 +52,11 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.ui.treeStructure.actions.CollapseAllAction;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.EditSourceOnDoubleClickHandler;
|
||||
import com.intellij.util.EditSourceOnEnterKeyHandler;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -68,6 +72,10 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author anna
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class FavoritesTreeViewPanel extends JPanel implements DataProvider {
|
||||
private final FavoritesTreeStructure myFavoritesTreeStructure;
|
||||
private FavoritesViewTreeBuilder myBuilder;
|
||||
@@ -167,6 +175,7 @@ public class FavoritesTreeViewPanel extends JPanel implements DataProvider {
|
||||
return CustomShortcutSet.fromString("DELETE");
|
||||
}
|
||||
})
|
||||
.addExtraAction(AnActionButton.fromAction(new CollapseAllAction(myTree)))
|
||||
.setLineBorder(0, 0, 0, 0)
|
||||
.createPanel();
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder(0));
|
||||
|
||||
+74
-12
@@ -16,19 +16,26 @@
|
||||
|
||||
package com.intellij.ide.favoritesTreeView;
|
||||
|
||||
import com.intellij.ide.SelectInContext;
|
||||
import com.intellij.ide.SelectInManager;
|
||||
import com.intellij.ide.StandardTargetWeights;
|
||||
import com.intellij.ide.impl.ProjectViewSelectInTarget;
|
||||
import com.intellij.ide.impl.SelectInTargetPsiWrapper;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: Feb 25, 2005
|
||||
* @author anna
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class FavoritesViewSelectInTarget extends ProjectViewSelectInTarget {
|
||||
public class FavoritesViewSelectInTarget extends SelectInTargetPsiWrapper {
|
||||
public FavoritesViewSelectInTarget(final Project project) {
|
||||
super(project);
|
||||
}
|
||||
@@ -37,8 +44,68 @@ public class FavoritesViewSelectInTarget extends ProjectViewSelectInTarget {
|
||||
return SelectInManager.FAVORITES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolWindowId() {
|
||||
return SelectInManager.FAVORITES;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void select(Object selector, VirtualFile virtualFile, boolean requestFocus) {
|
||||
select(myProject, selector, null, null, virtualFile, requestFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void select(PsiElement element, boolean requestFocus) {
|
||||
PsiElement toSelect = null;
|
||||
if (element instanceof PsiFile || element instanceof PsiDirectory) {
|
||||
toSelect = element;
|
||||
}
|
||||
else {
|
||||
final PsiFile containingFile = element.getContainingFile();
|
||||
if (containingFile == null) return;
|
||||
final FileViewProvider viewProvider = containingFile.getViewProvider();
|
||||
toSelect = viewProvider.getPsi(viewProvider.getBaseLanguage());
|
||||
}
|
||||
if (toSelect == null) return;
|
||||
PsiElement originalElement = toSelect.getOriginalElement();
|
||||
final VirtualFile virtualFile = PsiUtilBase.getVirtualFile(originalElement);
|
||||
select(originalElement, virtualFile, requestFocus);
|
||||
}
|
||||
|
||||
public static ActionCallback select(@NotNull Project project,
|
||||
final Object toSelect,
|
||||
@Nullable final String viewId,
|
||||
@Nullable final String subviewId,
|
||||
final VirtualFile virtualFile,
|
||||
final boolean requestFocus) {
|
||||
final ActionCallback result = new ActionCallback();
|
||||
|
||||
ToolWindowManager windowManager=ToolWindowManager.getInstance(project);
|
||||
final ToolWindow favoritesToolWindow = windowManager.getToolWindow(ToolWindowId.FAVORITES_VIEW);
|
||||
|
||||
if (favoritesToolWindow != null) {
|
||||
final FavoritesTreeViewPanel panel = UIUtil.findComponentOfType(favoritesToolWindow.getComponent(), FavoritesTreeViewPanel.class);
|
||||
|
||||
if (panel != null) {
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
panel.selectElement(toSelect, virtualFile, requestFocus);
|
||||
result.setDone();
|
||||
}
|
||||
};
|
||||
|
||||
if (requestFocus) {
|
||||
favoritesToolWindow.activate(runnable, false);
|
||||
} else {
|
||||
favoritesToolWindow.show(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean canSelect(final PsiFileSystemItem file) {
|
||||
if (!super.canSelect(file)) return false;
|
||||
return findSuitableFavoritesList(file.getVirtualFile(), myProject, null) != null;
|
||||
}
|
||||
|
||||
@@ -63,9 +130,4 @@ public class FavoritesViewSelectInTarget extends ProjectViewSelectInTarget {
|
||||
protected boolean canWorkWithCustomObjects() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSubIdSelectable(String subId, SelectInContext context) {
|
||||
final FavoritesManager favoritesManager = FavoritesManager.getInstance(myProject);
|
||||
return favoritesManager.contains(subId, context.getVirtualFile());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ import com.intellij.util.EditSourceOnDoubleClickHandler;
|
||||
import com.intellij.util.OpenSourceUtil;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -503,17 +502,7 @@ abstract class TodoPanel extends SimpleToolWindowPanel implements OccurenceNavig
|
||||
@Nullable
|
||||
private OccurenceInfo goToPointer(TodoItemNode pointer) {
|
||||
if (pointer == null) return null;
|
||||
DefaultMutableTreeNode node = myTodoTreeBuilder.getNodeForElement(pointer);
|
||||
if (node == null) {
|
||||
myTodoTreeBuilder.buildNodeForElement(pointer);
|
||||
node = myTodoTreeBuilder.getNodeForElement(pointer);
|
||||
if (node == null) {
|
||||
// TODO[vova] it seems that this check isn't required any more bacause it was side effect of SCR#7063
|
||||
// TODO[vova] try to remove this check in Aurora
|
||||
return null;
|
||||
}
|
||||
}
|
||||
TreeUtil.selectPath(myTree, new TreePath(node.getPath()));
|
||||
myTodoTreeBuilder.select(pointer);
|
||||
return new OccurenceInfo(
|
||||
new OpenFileDescriptor(myProject, pointer.getValue().getTodoItem().getFile().getVirtualFile(),
|
||||
pointer.getValue().getRangeMarker().getStartOffset()),
|
||||
|
||||
@@ -371,7 +371,10 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec
|
||||
});
|
||||
|
||||
if (ok[0]) {
|
||||
((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(myProject)).startRunInjectors(document, synchronously);
|
||||
// otherwise changes maybe not synced to the document yet, and injectors will crash
|
||||
if (!mySynchronizer.isDocumentAffectedByTransactions(document)) {
|
||||
((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(myProject)).startRunInjectors(document, synchronously);
|
||||
}
|
||||
// run after commit actions outside write action
|
||||
runAfterCommitActions(document);
|
||||
if (DebugUtil.DO_EXPENSIVE_CHECKS) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
@@ -161,6 +162,18 @@ public abstract class RenamePsiElementProcessor {
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitutes element to be renamed and initiate rename procedure. Should be used in order to prevent modal dialogs to appear during inplace rename
|
||||
* @param element the element on which refactoring was invoked
|
||||
* @param editor the editor in which inplace refactoring was invoked
|
||||
* @param renameCallback rename procedure which should be called on the chosen substitution
|
||||
*/
|
||||
public void substituteElementToRename(@NotNull final PsiElement element, @NotNull Editor editor, @NotNull Pass<PsiElement> renameCallback) {
|
||||
final PsiElement psiElement = substituteElementToRename(element, editor);
|
||||
if (psiElement == null) return;
|
||||
renameCallback.pass(psiElement);
|
||||
}
|
||||
|
||||
public void findCollisions(final PsiElement element, final String newName, final Map<? extends PsiElement, String> allRenames,
|
||||
final List<UsageInfo> result) {
|
||||
}
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.refactoring.rename.inplace;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionParameters;
|
||||
import com.intellij.codeInsight.completion.CompletionResultSet;
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateState;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 11/22/11
|
||||
*/
|
||||
public class CompletionContributorForInplaceRename extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
|
||||
final Editor editor = parameters.getLookup().getEditor();
|
||||
final TemplateState state = TemplateManagerImpl.getTemplateState(editor);
|
||||
if (state != null) {
|
||||
if (editor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER) != null) {
|
||||
result.stopHere();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-2
@@ -18,12 +18,15 @@ package com.intellij.refactoring.rename.inplace;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.lang.LanguageRefactoringSupport;
|
||||
import com.intellij.lang.refactoring.RefactoringSupportProvider;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -45,9 +48,20 @@ public class MemberInplaceRenameHandler extends VariableInplaceRenameHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VariableInplaceRenamer createRenamer(@NotNull PsiElement elementToRename, Editor editor) {
|
||||
public VariableInplaceRenamer doRename(@NotNull final PsiElement elementToRename, final Editor editor, final DataContext dataContext) {
|
||||
if (elementToRename instanceof PsiNameIdentifierOwner) {
|
||||
return new MemberInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor);
|
||||
RenamePsiElementProcessor.forElement(elementToRename).substituteElementToRename(elementToRename, editor, new Pass<PsiElement>() {
|
||||
@Override
|
||||
public void pass(PsiElement element) {
|
||||
final MemberInplaceRenamer renamer = new MemberInplaceRenamer((PsiNameIdentifierOwner)elementToRename, element, editor);
|
||||
boolean startedRename = renamer.performInplaceRename();
|
||||
if (!startedRename) {
|
||||
performDialogRename(elementToRename, editor, dataContext);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
performDialogRename(elementToRename, editor, dataContext);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+31
-14
@@ -25,6 +25,7 @@ import com.intellij.openapi.command.impl.FinishMarkAction;
|
||||
import com.intellij.openapi.command.impl.StartMarkAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -34,6 +35,7 @@ import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.rename.RenameProcessor;
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
|
||||
@@ -53,10 +55,15 @@ import java.util.List;
|
||||
*/
|
||||
public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
protected final String myOldName;
|
||||
private final PsiElement mySubstituted;
|
||||
private RangeMarker mySubstitutedRange;
|
||||
|
||||
public MemberInplaceRenamer(@NotNull PsiNameIdentifierOwner elementToRename, Editor editor) {
|
||||
public MemberInplaceRenamer(@NotNull PsiNameIdentifierOwner elementToRename, PsiElement substituted, Editor editor) {
|
||||
super(elementToRename, editor);
|
||||
myOldName = elementToRename.getName();
|
||||
mySubstituted = substituted;
|
||||
mySubstitutedRange = mySubstituted != null && mySubstituted != myElementToRename && mySubstituted.getTextRange() != null ? myEditor.getDocument().createRangeMarker(mySubstituted.getTextRange()) : null;
|
||||
|
||||
showDialogAdvertisement("RenameElement");
|
||||
}
|
||||
|
||||
@@ -99,8 +106,7 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
final ArrayList<PsiReference> references = new ArrayList<PsiReference>(super.collectRefs(referencesSearchScope));
|
||||
final PsiNamedElement variable = getVariable();
|
||||
if (variable != null) {
|
||||
final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(variable);
|
||||
final PsiElement substituted = processor.substituteElementToRename(variable, myEditor);
|
||||
final PsiElement substituted = getSubstituted();
|
||||
if (substituted != null && substituted != variable) {
|
||||
references.addAll(ReferencesSearch.search(substituted, referencesSearchScope, false).findAll());
|
||||
}
|
||||
@@ -126,11 +132,10 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
boolean showChooser = super.appendAdditionalElement(stringUsages);
|
||||
PsiNamedElement variable = getVariable();
|
||||
if (variable != null) {
|
||||
RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(variable);
|
||||
final PsiElement substituted = processor.substituteElementToRename(variable, myEditor);
|
||||
final PsiElement substituted = getSubstituted();
|
||||
if (substituted != null) {
|
||||
appendAdditionalElement(stringUsages, variable, substituted);
|
||||
processor = RenamePsiElementProcessor.forElement(substituted);
|
||||
RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(substituted);
|
||||
final HashMap<PsiElement, String> allRenames = new HashMap<PsiElement, String>();
|
||||
PsiFile currentFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
|
||||
processor.prepareRenaming(substituted, "", allRenames, new LocalSearchScope(currentFile));
|
||||
@@ -163,9 +168,8 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
final NamesValidator namesValidator = LanguageNamesValidation.INSTANCE.forLanguage(variable.getLanguage());
|
||||
LOG.assertTrue(namesValidator != null);
|
||||
if (namesValidator.isIdentifier(newName, myProject)) {
|
||||
RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(variable);
|
||||
final PsiElement substitutedElement = processor.substituteElementToRename(variable, myEditor);
|
||||
if (substitutedElement == null) {
|
||||
final PsiElement substituted = getSubstituted();
|
||||
if (substituted == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -173,13 +177,14 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
.message("renaming.0.1.to.2", UsageViewUtil.getType(variable), UsageViewUtil.getDescriptiveName(variable), newName);
|
||||
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
|
||||
public void run() {
|
||||
final RenamePsiElementProcessor elementProcessor = RenamePsiElementProcessor.forElement(substitutedElement);
|
||||
|
||||
final RenamePsiElementProcessor elementProcessor = RenamePsiElementProcessor.forElement(substituted);
|
||||
final RenameProcessor
|
||||
renameProcessor = new RenameProcessor(myProject, substitutedElement, newName,
|
||||
elementProcessor.isToSearchInComments(substitutedElement),
|
||||
elementProcessor.isToSearchForTextOccurrences(substitutedElement));
|
||||
renameProcessor = new RenameProcessor(myProject, substituted, newName,
|
||||
elementProcessor.isToSearchInComments(substituted),
|
||||
elementProcessor.isToSearchForTextOccurrences(substituted));
|
||||
for (AutomaticRenamerFactory factory : Extensions.getExtensions(AutomaticRenamerFactory.EP_NAME)) {
|
||||
if (factory.isApplicable(substitutedElement) && factory.getOptionName() != null) {
|
||||
if (factory.isApplicable(substituted) && factory.getOptionName() != null) {
|
||||
if (factory.isEnabled()) {
|
||||
renameProcessor.addRenamerFactory(factory);
|
||||
}
|
||||
@@ -254,4 +259,16 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
if (ex[0] != null) throw ex[0];
|
||||
return markAction[0];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getSubstituted() {
|
||||
if (mySubstituted != null && mySubstituted.isValid()) return mySubstituted;
|
||||
if (mySubstitutedRange != null) {
|
||||
final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
|
||||
if (psiFile != null) {
|
||||
return PsiTreeUtil.getParentOfType(psiFile.findElementAt(mySubstitutedRange.getStartOffset()), PsiNameIdentifierOwner.class);
|
||||
}
|
||||
}
|
||||
return getVariable();
|
||||
}
|
||||
}
|
||||
|
||||
+16
-13
@@ -112,23 +112,26 @@ public class VariableInplaceRenameHandler implements RenameHandler {
|
||||
boolean startedRename = renamer == null ? false : renamer.performInplaceRename();
|
||||
|
||||
if (!startedRename) {
|
||||
try {
|
||||
ourPreventInlineRenameFlag.set(Boolean.TRUE);
|
||||
|
||||
RenameHandler handler = RenameHandlerRegistry.getInstance().getRenameHandler(dataContext);
|
||||
assert handler != null;
|
||||
handler.invoke(
|
||||
elementToRename.getProject(),
|
||||
editor,
|
||||
elementToRename.getContainingFile(), dataContext
|
||||
);
|
||||
} finally {
|
||||
ourPreventInlineRenameFlag.set(null);
|
||||
}
|
||||
performDialogRename(elementToRename, editor, dataContext);
|
||||
}
|
||||
return renamer;
|
||||
}
|
||||
|
||||
protected static void performDialogRename(PsiElement elementToRename, Editor editor, DataContext dataContext) {
|
||||
try {
|
||||
ourPreventInlineRenameFlag.set(Boolean.TRUE);
|
||||
RenameHandler handler = RenameHandlerRegistry.getInstance().getRenameHandler(dataContext);
|
||||
assert handler != null;
|
||||
handler.invoke(
|
||||
elementToRename.getProject(),
|
||||
editor,
|
||||
elementToRename.getContainingFile(), dataContext
|
||||
);
|
||||
} finally {
|
||||
ourPreventInlineRenameFlag.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected VariableInplaceRenamer createRenamer(@NotNull PsiElement elementToRename, Editor editor) {
|
||||
return new VariableInplaceRenamer((PsiNameIdentifierOwner)elementToRename, editor);
|
||||
|
||||
@@ -932,7 +932,8 @@ public class FileBasedIndex implements ApplicationComponent {
|
||||
|
||||
public static @Nullable Throwable getCauseToRebuildIndex(RuntimeException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof StorageException || cause instanceof IOException || cause instanceof IllegalArgumentException) return cause;
|
||||
if (cause instanceof StorageException || cause instanceof IOException ||
|
||||
cause instanceof IllegalArgumentException || cause instanceof IllegalStateException) return cause;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
|
||||
private boolean myEnabled = true;
|
||||
private boolean myVisible = true;
|
||||
private ShortcutSet myShortcut;
|
||||
private AnAction myAction = null;
|
||||
private JComponent myContextComponent;
|
||||
|
||||
public AnActionButton(String text) {
|
||||
@@ -47,6 +48,29 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
|
||||
|
||||
public AnActionButton() {
|
||||
}
|
||||
|
||||
public static AnActionButton fromAction(final AnAction action) {
|
||||
final Presentation presentation = action.getTemplatePresentation();
|
||||
return new AnActionButton(presentation.getText(),
|
||||
presentation.getDescription(),
|
||||
presentation.getIcon()) {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
action.actionPerformed(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButton(AnActionEvent e) {
|
||||
action.update(e);
|
||||
final boolean enabled = e.getPresentation().isEnabled();
|
||||
final boolean visible = e.getPresentation().isVisible();
|
||||
if (enabled && visible) {
|
||||
super.updateButton(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return myEnabled;
|
||||
@@ -66,9 +90,17 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
|
||||
|
||||
@Override
|
||||
public final void update(AnActionEvent e) {
|
||||
final boolean enabled = isEnabled() && isContextComponentOk();
|
||||
boolean myActionVisible = true;
|
||||
boolean myActionEnabled = true;
|
||||
if (myAction != null) {
|
||||
myAction.update(e);
|
||||
myActionEnabled = myAction.getTemplatePresentation().isEnabled();
|
||||
myActionVisible = myAction.getTemplatePresentation().isVisible();
|
||||
}
|
||||
final boolean enabled = isEnabled() && isContextComponentOk() && myActionEnabled;
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
e.getPresentation().setVisible(isVisible());
|
||||
e.getPresentation().setVisible(isVisible() && myActionVisible);
|
||||
|
||||
if (enabled) {
|
||||
updateButton(e);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@ import javax.swing.*;
|
||||
public class TabsUtil {
|
||||
|
||||
|
||||
public static final int TAB_VERTICAL_PADDING = 3;
|
||||
public static final int TABS_BORDER = 1;
|
||||
public static final int TAB_VERTICAL_PADDING = 2;
|
||||
public static final int TABS_BORDER = 1;
|
||||
|
||||
public static final int ACTIVE_TAB_UNDERLINE_HEIGHT = 4;
|
||||
|
||||
private TabsUtil() {
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.tabs.JBTabsPosition;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.TabsUtil;
|
||||
import com.intellij.util.ui.SameColor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -69,16 +70,24 @@ public class JBEditorTabs extends JBTabsImpl {
|
||||
int _height = effectiveBounds.height - insets.top - insets.bottom;
|
||||
|
||||
|
||||
if ((!isSingleRow() && label.getBounds().y > 0 /* for multiline */) || (isSingleRow() && isHorizontalTabs())) {
|
||||
if (isSingleRow() && getPosition() == JBTabsPosition.bottom) {
|
||||
_y += TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
|
||||
} else {
|
||||
_height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
Color tabColor = label.getInfo().getTabColor();
|
||||
if (tabColor != null) {
|
||||
//g2d.setPaint(new LinearGradientPaint(_x, _y, _x, _y + effectiveBounds.height, new float[] {.3f, .6f, 1f}, new Color[] {new SameColor(170), new SameColor(150), new SameColor(90)}));
|
||||
g2d.setPaint(new GradientPaint(_x, _y, new SameColor(170), _x, _y + effectiveBounds.height, new SameColor(150)));
|
||||
g2d.setPaint(new GradientPaint(_x, _y, new SameColor(200), _x, _y + effectiveBounds.height, new SameColor(130)));
|
||||
g2d.fillRect(_x, _y, _width, _height);
|
||||
|
||||
g2d.setColor(new Color(tabColor.getRed(), tabColor.getGreen(), tabColor.getBlue(), 150));
|
||||
g2d.fillRect(_x, _y, _width, _height);
|
||||
} else {
|
||||
g2d.setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 140), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 90)));
|
||||
g2d.setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 180), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 100)));
|
||||
g2d.fillRect(_x, _y, _width, _height);
|
||||
}
|
||||
|
||||
@@ -130,7 +139,9 @@ public class JBEditorTabs extends JBTabsImpl {
|
||||
int y = r2.y + insets.top;
|
||||
int height = maxLength - insets.top - insets.bottom;
|
||||
if (getTabsPosition() == JBTabsPosition.bottom) {
|
||||
y = r2.height - height - insets.top;
|
||||
y = r2.height - height - insets.top + TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
|
||||
} else {
|
||||
height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
|
||||
}
|
||||
|
||||
rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height);
|
||||
@@ -163,22 +174,20 @@ public class JBEditorTabs extends JBTabsImpl {
|
||||
int _x = r.x;
|
||||
int _y = r.y;
|
||||
int _height = r.height;
|
||||
|
||||
//g2d.setColor(Color.WHITE);
|
||||
//g2d.draw(
|
||||
// selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY()
|
||||
// - selectedShape.labelPath.deltaY(3), selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(3)));
|
||||
|
||||
if (getPosition() == JBTabsPosition.left || getPosition() == JBTabsPosition.right) {
|
||||
g2d.setColor(new Color(0, 0, 0, 45));
|
||||
g2d.draw(
|
||||
selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY()
|
||||
- selectedShape.labelPath.deltaY(4), selectedShape.path.getMaxX(),
|
||||
selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(4)));
|
||||
|
||||
g2d.setColor(new Color(0, 0, 0, 45));
|
||||
g2d.draw(
|
||||
selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY()
|
||||
- selectedShape.labelPath.deltaY(4), selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(4)));
|
||||
|
||||
g2d.setColor(new Color(0, 0, 0, 15));
|
||||
g2d.draw(
|
||||
selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY()
|
||||
- selectedShape.labelPath.deltaY(5), selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(5)));
|
||||
g2d.setColor(new Color(0, 0, 0, 15));
|
||||
g2d.draw(
|
||||
selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY()
|
||||
- selectedShape.labelPath.deltaY(5), selectedShape.path.getMaxX(),
|
||||
selectedShape.labelPath.getMaxY() - selectedShape.labelPath.deltaY(5)));
|
||||
}
|
||||
|
||||
Color tabColor = label.getInfo().getTabColor();
|
||||
if (tabColor != null) {
|
||||
@@ -201,26 +210,31 @@ public class JBEditorTabs extends JBTabsImpl {
|
||||
selectedShape.labelPath.deltaY(1),
|
||||
selectedShape.labelPath.getMaxX() - selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() -
|
||||
selectedShape.labelPath.deltaY(4)));
|
||||
|
||||
// side shadow
|
||||
g2d.setColor(new Color(0, 0, 0, 30));
|
||||
g2d.draw(selectedShape.labelPath
|
||||
.transformLine(selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getY() +
|
||||
selectedShape.labelPath.deltaY(1),
|
||||
selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() -
|
||||
selectedShape.labelPath.deltaY(4)));
|
||||
|
||||
boolean horizontal = getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom;
|
||||
|
||||
g2d.draw(selectedShape.labelPath
|
||||
.transformLine(selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1), selectedShape.labelPath.getY() +
|
||||
selectedShape.labelPath.deltaY(1),
|
||||
selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1), selectedShape.labelPath.getMaxY() -
|
||||
selectedShape.labelPath.deltaY(4)));
|
||||
|
||||
if (!isHorizontalTabs()) {
|
||||
// side shadow
|
||||
g2d.setColor(new Color(0, 0, 0, 30));
|
||||
g2d.draw(selectedShape.labelPath
|
||||
.transformLine(selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getY() +
|
||||
selectedShape.labelPath.deltaY(1),
|
||||
selectedShape.labelPath.getMaxX() + selectedShape.labelPath.deltaX(1), selectedShape.labelPath.getMaxY() -
|
||||
selectedShape.labelPath.deltaY(4)));
|
||||
|
||||
boolean horizontal = getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom;
|
||||
|
||||
g2d.draw(selectedShape.labelPath
|
||||
.transformLine(selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1),
|
||||
selectedShape.labelPath.getY() +
|
||||
selectedShape.labelPath.deltaY(1),
|
||||
selectedShape.labelPath.getX() - selectedShape.labelPath.deltaX(horizontal ? 2 : 1),
|
||||
selectedShape.labelPath.getMaxY() -
|
||||
selectedShape.labelPath.deltaY(4)));
|
||||
}
|
||||
|
||||
g2d.setColor(new Color(0, 0, 0, 50));
|
||||
g2d.draw(selectedShape.labelPath.transformLine(i.left, selectedShape.labelPath.getMaxY(),
|
||||
selectedShape.path.getMaxX(), selectedShape.labelPath.getMaxY()));
|
||||
selectedShape.path.getMaxX(),
|
||||
selectedShape.labelPath.getMaxY()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -235,7 +249,7 @@ public class JBEditorTabs extends JBTabsImpl {
|
||||
shape.insets = shape.path.transformInsets(getLayoutInsets());
|
||||
shape.labelPath = shape.path.createTransform(getSelectedLabel().getBounds());
|
||||
|
||||
shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(3);
|
||||
shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1);
|
||||
shape.labelTopY =
|
||||
shape.labelPath.getY() + (getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom ? shape.labelPath.deltaY(1) : 0) ;
|
||||
shape.labelLeftX = shape.labelPath.getX() + (getPosition() == JBTabsPosition.top || getPosition() == JBTabsPosition.bottom ? 0 : shape.labelPath.deltaX(
|
||||
@@ -253,8 +267,8 @@ public class JBEditorTabs extends JBTabsImpl {
|
||||
int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right);
|
||||
|
||||
shape.path.lineTo(lastX, shape.labelBottomY);
|
||||
shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(3));
|
||||
shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(3));
|
||||
shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1));
|
||||
shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1));
|
||||
|
||||
shape.path.closePath();
|
||||
shape.fillPath = shape.path.copy();
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.ui.SimpleColoredText;
|
||||
import com.intellij.ui.components.panels.Wrapper;
|
||||
import com.intellij.ui.tabs.JBTabsPosition;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.TabsUtil;
|
||||
import com.intellij.ui.tabs.UiDecorator;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import com.intellij.util.ui.Centerizer;
|
||||
@@ -223,11 +224,11 @@ public class TabLabel extends JPanel {
|
||||
}
|
||||
|
||||
private int getNonSelectedOffset() {
|
||||
return myTabs.isEditorTabs() ? 0 : 2;
|
||||
return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 2;
|
||||
}
|
||||
|
||||
private int getSelectedOffset() {
|
||||
return myTabs.isEditorTabs() ? 0 : 1;
|
||||
return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -236,7 +237,7 @@ public class TabLabel extends JPanel {
|
||||
|
||||
final JBTabsPosition pos = myTabs.getTabsPosition();
|
||||
switch (pos) {
|
||||
case top: case bottom: size.height += getSelectedOffset(); break;
|
||||
case top: case bottom: size.height += myTabs.isEditorTabs() ? TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT : getSelectedOffset(); break;
|
||||
case left: case right: size.width += getSelectedOffset(); break;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.ui.tabs.impl.table;
|
||||
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.TabsUtil;
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl;
|
||||
import com.intellij.ui.tabs.impl.LayoutPassInfo;
|
||||
import com.intellij.ui.tabs.impl.TabLabel;
|
||||
@@ -118,6 +119,9 @@ public class TableLayout extends TabLayout {
|
||||
final Insets insets = myTabs.getLayoutInsets();
|
||||
int eachY = insets.top;
|
||||
int eachX;
|
||||
int row = 0;
|
||||
final int tabUnderlineFix = myTabs.isEditorTabs() ? TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT : 0;
|
||||
|
||||
for (TableRow eachRow : data.table) {
|
||||
eachX = insets.left;
|
||||
|
||||
@@ -142,14 +146,15 @@ public class TableLayout extends TabLayout {
|
||||
width = data.toFitRec.width + insets.left - eachX;
|
||||
}
|
||||
|
||||
|
||||
myTabs.layout(label, eachX, eachY, width, myTabs.myHeaderFitSize.height);
|
||||
myTabs.layout(label, eachX, eachY, width, row < data.table.size() - 1 ? myTabs.myHeaderFitSize.height - tabUnderlineFix : myTabs.myHeaderFitSize.height);
|
||||
label.setAligmentToCenter(deltaToFit > 0);
|
||||
|
||||
boolean lastCell = i == eachRow.myColumns.size() - 1;
|
||||
eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength());
|
||||
}
|
||||
eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength();
|
||||
eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0);
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
if (myTabs.getSelectedInfo() != null) {
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
|
||||
}
|
||||
final InstalledPluginsTableModel installedPluginsModel = (InstalledPluginsTableModel)installed.getPluginsModel();
|
||||
for (PluginNode node : list) {
|
||||
installedPluginsModel.appendDescriptor(node);
|
||||
installedPluginsModel.appendOrUpdateDescriptor(node);
|
||||
}
|
||||
installed.setRequireShutdown(true);
|
||||
}
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ public class InstalledPluginsManagerMain extends PluginManagerMain {
|
||||
return;
|
||||
}
|
||||
PluginDownloader.install(file, file.getName());
|
||||
((InstalledPluginsTableModel)pluginsModel).appendDescriptor(pluginDescriptor);
|
||||
((InstalledPluginsTableModel)pluginsModel).appendOrUpdateDescriptor(pluginDescriptor);
|
||||
select(pluginDescriptor);
|
||||
setRequireShutdown(true);
|
||||
}
|
||||
|
||||
+11
-5
@@ -84,11 +84,17 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
setSortKey(new RowSorter.SortKey(getNameColumn(), SortOrder.ASCENDING));
|
||||
}
|
||||
|
||||
public void appendDescriptor(IdeaPluginDescriptor descriptor) {
|
||||
myInstalled.add(descriptor);
|
||||
view.add(descriptor);
|
||||
setEnabled(descriptor, true);
|
||||
fireTableDataChanged();
|
||||
public void appendOrUpdateDescriptor(IdeaPluginDescriptor descriptor) {
|
||||
final PluginId descrId = descriptor.getPluginId();
|
||||
final IdeaPluginDescriptor existing = PluginManager.getPlugin(descrId);
|
||||
if (existing != null) {
|
||||
updateExistingPluginInfo(descriptor, existing);
|
||||
} else {
|
||||
myInstalled.add(descriptor);
|
||||
view.add(descriptor);
|
||||
setEnabled(descriptor, true);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getCheckboxColumn() {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.injected.editor;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.ex.DisposableIterator;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
import com.intellij.openapi.editor.ex.SweepProcessor;
|
||||
@@ -25,15 +26,13 @@ import com.intellij.openapi.editor.impl.event.MarkupModelListener;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
@@ -146,7 +145,7 @@ public class MarkupModelWindow extends UserDataHolderBase implements MarkupModel
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
|
||||
public DisposableIterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
|
||||
// todo convert
|
||||
return myHostModel.overlappingIterator(startOffset, endOffset);
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@ import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
@@ -46,7 +44,7 @@ public interface MarkupModelEx extends MarkupModel {
|
||||
boolean processRangeHighlightersOutside(int start, int end, @NotNull Processor<? super RangeHighlighterEx> processor);
|
||||
|
||||
@NotNull
|
||||
Iterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset);
|
||||
DisposableIterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset);
|
||||
|
||||
// optimization: creates highlighter and fires only one event: highlighterCreated
|
||||
RangeHighlighterEx addRangeHighlighterAndChangeAttributes(int startOffset,
|
||||
|
||||
@@ -320,26 +320,32 @@ public class EditorUtil {
|
||||
EditorEx editorImpl = (EditorEx)editor;
|
||||
int offset = start;
|
||||
IterationState state = new IterationState(editorImpl, start, end, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int column = currentColumn[0];
|
||||
int spaceSize = getSpaceWidth(fontType, editorImpl);
|
||||
for (; column < columnNumber && offset < end; offset++) {
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
int column;
|
||||
try {
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
column = currentColumn[0];
|
||||
int spaceSize = getSpaceWidth(fontType, editorImpl);
|
||||
for (; column < columnNumber && offset < end; offset++) {
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
char c = text.charAt(offset);
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = nextTabStop(x, editorImpl);
|
||||
column += columnsNumber(x - prevX, spaceSize);
|
||||
}
|
||||
else {
|
||||
x += charWidth(c, fontType, editorImpl);
|
||||
column++;
|
||||
char c = text.charAt(offset);
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = nextTabStop(x, editorImpl);
|
||||
column += columnsNumber(x - prevX, spaceSize);
|
||||
}
|
||||
else {
|
||||
x += charWidth(c, fontType, editorImpl);
|
||||
column++;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
state.dispose();
|
||||
}
|
||||
|
||||
if (column == columnNumber) {
|
||||
return offset;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -46,6 +46,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.diff.FilesTooBigForDiffException;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
@@ -186,21 +187,21 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
public void moveToOffset(int offset, boolean locateBeforeSoftWrap) {
|
||||
assertIsDispatchThread();
|
||||
validateCallContext();
|
||||
moveToLogicalPosition(myEditor.offsetToLogicalPosition(offset), locateBeforeSoftWrap);
|
||||
if (!ignoreWrongMoves && !myEditor.offsetToLogicalPosition(myOffset).equals(myEditor.offsetToLogicalPosition(offset))) {
|
||||
StringBuilder documentInfo = new StringBuilder();
|
||||
Document document = myEditor.getDocument();
|
||||
for (int line = 0; line < document.getLineCount(); line++) {
|
||||
documentInfo.append(line).append(": ").append(document.getLineStartOffset(line)).append("-")
|
||||
.append(document.getLineEndOffset(line)).append(", ");
|
||||
}
|
||||
if (documentInfo.length() > 0) {
|
||||
documentInfo.setLength(documentInfo.length() - 1);
|
||||
}
|
||||
final LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(offset);
|
||||
moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, null);
|
||||
if (!ignoreWrongMoves && !myEditor.offsetToLogicalPosition(myOffset).equals(logicalPosition)) {
|
||||
StringBuilder debugBuffer = new StringBuilder();
|
||||
moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, debugBuffer);
|
||||
int textStart = Math.max(0, Math.min(offset, myOffset) - 1);
|
||||
final DocumentEx document = myEditor.getDocument();
|
||||
int textEnd = Math.min(document.getTextLength() - 1, Math.max(offset, myOffset) + 1);
|
||||
CharSequence text = document.getCharsSequence().subSequence(textStart, textEnd);
|
||||
LOG.error(
|
||||
"caret moved to wrong offset. Requested: offset=" + offset + ", logical position=" + myEditor.offsetToLogicalPosition(offset)
|
||||
"caret moved to wrong offset. Requested: offset=" + offset + ", logical position=" + logicalPosition
|
||||
+ " but actual: offset=" + myOffset + ", logical position=" + myLogicalCaret + "(" + myEditor.offsetToLogicalPosition(myOffset)
|
||||
+ "). " + myEditor.dumpState()
|
||||
+ "\n interested text [" + textStart + "; " + textEnd + "): '" + text + "'"
|
||||
+ "\n debug trace: " + debugBuffer
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -361,11 +362,16 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
|
||||
@Override
|
||||
public void moveToLogicalPosition(@NotNull LogicalPosition pos) {
|
||||
moveToLogicalPosition(pos, false);
|
||||
moveToLogicalPosition(pos, false, null);
|
||||
}
|
||||
|
||||
private void moveToLogicalPosition(LogicalPosition pos, boolean locateBeforeSoftWrap) {
|
||||
private void moveToLogicalPosition(@NotNull LogicalPosition pos, boolean locateBeforeSoftWrap, @Nullable StringBuilder debugBuffer) {
|
||||
assertIsDispatchThread();
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append(String.format(
|
||||
"Start moveToLogicalPosition(). Locate before soft wrap: %b, position: %s", locateBeforeSoftWrap, pos
|
||||
));
|
||||
}
|
||||
myDesiredX = -1;
|
||||
validateCallContext();
|
||||
int column = pos.column;
|
||||
@@ -377,10 +383,16 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
Document doc = myEditor.getDocument();
|
||||
|
||||
if (column < 0) {
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append("Resetting target logical column to zero as it is negative (" + column + ")");
|
||||
}
|
||||
column = 0;
|
||||
softWrapColumns = 0;
|
||||
}
|
||||
if (line < 0) {
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append("Resetting target logical line to zero as it is negative (" + line + ")");
|
||||
}
|
||||
line = 0;
|
||||
softWrapLinesBefore = 0;
|
||||
softWrapLinesCurrent = 0;
|
||||
@@ -388,9 +400,17 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
|
||||
int lineCount = doc.getLineCount();
|
||||
if (lineCount == 0) {
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append("Resetting target logical line to zero as the document is empty");
|
||||
}
|
||||
line = 0;
|
||||
}
|
||||
else if (line > lineCount - 1) {
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append(String.format(
|
||||
"Resetting target logical line (%d) to %d as it is greater than total document lines number", line, lineCount - 1
|
||||
));
|
||||
}
|
||||
line = lineCount - 1;
|
||||
softWrapLinesBefore = 0;
|
||||
softWrapLinesCurrent = 0;
|
||||
@@ -400,12 +420,21 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
|
||||
if (!editorSettings.isVirtualSpace() && line < lineCount && !myEditor.getSelectionModel().hasBlockSelection()) {
|
||||
int lineEndOffset = doc.getLineEndOffset(line);
|
||||
int lineEndColumnNumber = myEditor.offsetToLogicalPosition(lineEndOffset).column;
|
||||
final LogicalPosition endLinePosition = myEditor.offsetToLogicalPosition(lineEndOffset);
|
||||
int lineEndColumnNumber = endLinePosition.column;
|
||||
if (column > lineEndColumnNumber) {
|
||||
int oldColumn = column;
|
||||
column = lineEndColumnNumber;
|
||||
if (softWrapColumns != 0) {
|
||||
softWrapColumns -= column - lineEndColumnNumber;
|
||||
}
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append(String.format(
|
||||
"Resetting target logical column (%d) to %d because caret is not allowed to be located after line end (offset: %d, "
|
||||
+ "logical position: %s). Current soft wrap columns value: %d",
|
||||
oldColumn, lineEndColumnNumber, lineEndOffset, endLinePosition, softWrapColumns
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,12 +453,17 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
logicalPositionToUse = new LogicalPosition(line, column);
|
||||
}
|
||||
setCurrentLogicalCaret(logicalPositionToUse);
|
||||
|
||||
final int offset = myEditor.logicalPositionToOffset(myLogicalCaret);
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append(String.format("Resulting logical position to use: %s. It's mapped to offset %d", myLogicalCaret, offset));
|
||||
}
|
||||
|
||||
FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset);
|
||||
|
||||
if (collapsedAt != null && offset > collapsedAt.getStartOffset()) {
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append("Scheduling expansion of fold region ").append(collapsedAt);
|
||||
}
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -447,6 +481,9 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
|
||||
|
||||
myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append(String.format("Storing offset %d (mapped from logical position %s)", myOffset, myLogicalCaret));
|
||||
}
|
||||
LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());
|
||||
|
||||
myVisualLineStart = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
|
||||
@@ -458,7 +495,13 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) {
|
||||
int lineToUse = myVisibleCaret.line - 1;
|
||||
if (lineToUse >= 0) {
|
||||
moveToVisualPosition(new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse)));
|
||||
final VisualPosition visualPosition = new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse));
|
||||
if (debugBuffer != null) {
|
||||
debugBuffer.append(String.format(
|
||||
"Adjusting caret position by moving it before soft wrap. Moving to visual position %s", visualPosition
|
||||
));
|
||||
}
|
||||
moveToVisualPosition(visualPosition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -561,7 +604,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
finishUpdate();
|
||||
|
||||
DocumentEventImpl event = (DocumentEventImpl)e;
|
||||
final Document document = myEditor.getDocument();
|
||||
final DocumentEx document = myEditor.getDocument();
|
||||
boolean performSoftWrapAdjustment = e.getNewLength() > 0 // We want to put caret just after the last added symbol
|
||||
// There is a possible case that the user removes text just before the soft wrap. We want to keep caret
|
||||
// on a visual line with soft wrap start then.
|
||||
@@ -576,7 +619,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
final int line;
|
||||
try {
|
||||
line = event.translateLineViaDiff(myLogicalCaret.line);
|
||||
moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment);
|
||||
moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment, null);
|
||||
}
|
||||
catch (FilesTooBigForDiffException e1) {
|
||||
LOG.info(e1);
|
||||
@@ -585,7 +628,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (document instanceof DocumentEx && ((DocumentEx)document).isInBulkUpdate()) return;
|
||||
if (document.isInBulkUpdate()) return;
|
||||
int startOffset = e.getOffset();
|
||||
int oldEndOffset = startOffset + e.getOldLength();
|
||||
|
||||
|
||||
+55
-50
@@ -399,64 +399,69 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
int docLength = document.getTextLength();
|
||||
int patchedStartOffset = startOffset < docLength ? document.getLineStartOffset(document.getLineNumber(startOffset)) : docLength;
|
||||
int patchedEndOffset = endOffset <= docLength ? document.getLineEndOffset(document.getLineNumber(endOffset)) + 1 : docLength;
|
||||
Iterator<RangeHighlighterEx> docHighlighters = docMarkup.overlappingIterator(patchedStartOffset, patchedEndOffset);
|
||||
DisposableIterator<RangeHighlighterEx> docHighlighters = docMarkup.overlappingIterator(patchedStartOffset, patchedEndOffset);
|
||||
|
||||
final MarkupModelEx editorMarkup = (MarkupModelEx)myEditor.getMarkupModel();
|
||||
Iterator<RangeHighlighterEx> editorHighlighters = editorMarkup.overlappingIterator(startOffset, endOffset);
|
||||
DisposableIterator<RangeHighlighterEx> editorHighlighters = editorMarkup.overlappingIterator(startOffset, endOffset);
|
||||
|
||||
RangeHighlighterEx lastDocHighlighter = null;
|
||||
RangeHighlighterEx lastEditorHighlighter = null;
|
||||
try {
|
||||
RangeHighlighterEx lastDocHighlighter = null;
|
||||
RangeHighlighterEx lastEditorHighlighter = null;
|
||||
while (true) {
|
||||
if (lastDocHighlighter == null && docHighlighters.hasNext()) {
|
||||
lastDocHighlighter = docHighlighters.next();
|
||||
if (!lastDocHighlighter.isValid() || lastDocHighlighter.getAffectedAreaStartOffset() > endOffset) {
|
||||
lastDocHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
if (lastDocHighlighter.getAffectedAreaEndOffset() < startOffset) {
|
||||
lastDocHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (lastDocHighlighter == null && docHighlighters.hasNext()) {
|
||||
lastDocHighlighter = docHighlighters.next();
|
||||
if (!lastDocHighlighter.isValid() || lastDocHighlighter.getAffectedAreaStartOffset() > endOffset) {
|
||||
if (lastEditorHighlighter == null && editorHighlighters.hasNext()) {
|
||||
lastEditorHighlighter = editorHighlighters.next();
|
||||
if (!lastEditorHighlighter.isValid() || lastEditorHighlighter.getAffectedAreaStartOffset() > endOffset) {
|
||||
lastEditorHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
if (lastEditorHighlighter.getAffectedAreaEndOffset() < startOffset) {
|
||||
lastEditorHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDocHighlighter == null && lastEditorHighlighter == null) return;
|
||||
|
||||
final RangeHighlighterEx lowerHighlighter;
|
||||
|
||||
if (less(lastDocHighlighter, lastEditorHighlighter)) {
|
||||
lowerHighlighter = lastDocHighlighter;
|
||||
lastDocHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
if (lastDocHighlighter.getAffectedAreaEndOffset() < startOffset) {
|
||||
lastDocHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastEditorHighlighter == null && editorHighlighters.hasNext()) {
|
||||
lastEditorHighlighter = editorHighlighters.next();
|
||||
if (!lastEditorHighlighter.isValid() || lastEditorHighlighter.getAffectedAreaStartOffset() > endOffset) {
|
||||
else {
|
||||
lowerHighlighter = lastEditorHighlighter;
|
||||
lastEditorHighlighter = null;
|
||||
continue;
|
||||
}
|
||||
if (lastEditorHighlighter.getAffectedAreaEndOffset() < startOffset) {
|
||||
lastEditorHighlighter = null;
|
||||
continue;
|
||||
|
||||
assert lowerHighlighter != null;
|
||||
if (!lowerHighlighter.isValid()) continue;
|
||||
|
||||
int startLineIndex = lowerHighlighter.getDocument().getLineNumber(startOffset);
|
||||
if (startLineIndex < 0 || startLineIndex >= document.getLineCount()) continue;
|
||||
|
||||
int endLineIndex = lowerHighlighter.getDocument().getLineNumber(endOffset);
|
||||
if (endLineIndex < 0 || endLineIndex >= document.getLineCount()) continue;
|
||||
|
||||
if (lowerHighlighter.getEditorFilter().avaliableIn(myEditor)) {
|
||||
processor.process(lowerHighlighter);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDocHighlighter == null && lastEditorHighlighter == null) return;
|
||||
|
||||
final RangeHighlighterEx lowerHighlighter;
|
||||
|
||||
if (less(lastDocHighlighter, lastEditorHighlighter)) {
|
||||
lowerHighlighter = lastDocHighlighter;
|
||||
lastDocHighlighter = null;
|
||||
}
|
||||
else {
|
||||
lowerHighlighter = lastEditorHighlighter;
|
||||
lastEditorHighlighter = null;
|
||||
}
|
||||
|
||||
assert lowerHighlighter != null;
|
||||
if (!lowerHighlighter.isValid()) continue;
|
||||
|
||||
int startLineIndex = lowerHighlighter.getDocument().getLineNumber(startOffset);
|
||||
if (startLineIndex < 0 || startLineIndex >= document.getLineCount()) continue;
|
||||
|
||||
int endLineIndex = lowerHighlighter.getDocument().getLineNumber(endOffset);
|
||||
if (endLineIndex < 0 || endLineIndex >= document.getLineCount()) continue;
|
||||
|
||||
if (lowerHighlighter.getEditorFilter().avaliableIn(myEditor)) {
|
||||
processor.process(lowerHighlighter);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
docHighlighters.dispose();
|
||||
editorHighlighters.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -968,7 +973,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationsShown() {
|
||||
return myTextAnnotationGutters.size() > 0;
|
||||
return !myTextAnnotationGutters.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1122,7 +1127,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
if (toolTip != null && toolTip.length() != 0) {
|
||||
if (toolTip != null && !toolTip.isEmpty()) {
|
||||
final Ref<Point> t = new Ref<Point>(e.getPoint());
|
||||
int line = myEditor.yPositionToLogicalLine(e.getY());
|
||||
ArrayList<GutterIconRenderer> row = myLineToGutterRenderers.get(line);
|
||||
|
||||
@@ -985,10 +985,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
// We mark that we're under such circumstances then.
|
||||
boolean activeSoftWrapProcessed = logicalPosition.softWrapLinesOnCurrentLogicalLine <= 0;
|
||||
|
||||
int column = 0;
|
||||
int prevX = 0;
|
||||
CharSequence text = myDocument.getCharsNoThreadCheck();
|
||||
char c = ' ';
|
||||
|
||||
LogicalPosition endLogicalPosition = visualToLogicalPosition(new VisualPosition(line+1, 0));
|
||||
int endOffset = logicalPositionToOffset(endLogicalPosition);
|
||||
@@ -1004,125 +1001,133 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
IterationState state = new IterationState(this, offset, endOffset, false);
|
||||
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
try {
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
|
||||
int x = 0;
|
||||
int charWidth;
|
||||
boolean onSoftWrapDrawing = false;
|
||||
outer:
|
||||
while (true) {
|
||||
charWidth = -1;
|
||||
if (offset >= textLength) {
|
||||
break;
|
||||
}
|
||||
int x = 0;
|
||||
int charWidth;
|
||||
boolean onSoftWrapDrawing = false;
|
||||
char c = ' ';
|
||||
int prevX = 0;
|
||||
int column = 0;
|
||||
outer:
|
||||
while (true) {
|
||||
charWidth = -1;
|
||||
if (offset >= textLength) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
SoftWrap softWrap = mySoftWrapModel.getSoftWrap(offset);
|
||||
if (softWrap != null) {
|
||||
if (activeSoftWrapProcessed) {
|
||||
prevX = x;
|
||||
charWidth = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
onSoftWrapDrawing = true;
|
||||
SoftWrap softWrap = mySoftWrapModel.getSoftWrap(offset);
|
||||
if (softWrap != null) {
|
||||
if (activeSoftWrapProcessed) {
|
||||
prevX = x;
|
||||
charWidth = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
onSoftWrapDrawing = true;
|
||||
}
|
||||
else {
|
||||
column++;
|
||||
}
|
||||
break outer;
|
||||
}
|
||||
else {
|
||||
column++;
|
||||
}
|
||||
break outer;
|
||||
}
|
||||
else {
|
||||
CharSequence softWrapText = softWrap.getText();
|
||||
for (int i = 1/*Assuming line feed is located at the first position*/; i < softWrapText.length(); i++) {
|
||||
c = softWrapText.charAt(i);
|
||||
CharSequence softWrapText = softWrap.getText();
|
||||
for (int i = 1/*Assuming line feed is located at the first position*/; i < softWrapText.length(); i++) {
|
||||
c = softWrapText.charAt(i);
|
||||
prevX = x;
|
||||
charWidth = charToVisibleWidth(c, fontType, x);
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
break outer;
|
||||
}
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
}
|
||||
|
||||
// Process 'after soft wrap' sign.
|
||||
prevX = x;
|
||||
charWidth = charToVisibleWidth(c, fontType, x);
|
||||
charWidth = mySoftWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
x += charWidth;
|
||||
if (x >= px) {
|
||||
onSoftWrapDrawing = true;
|
||||
break outer;
|
||||
}
|
||||
column++;
|
||||
activeSoftWrapProcessed = true;
|
||||
}
|
||||
}
|
||||
FoldRegion region = state.getCurrentFold();
|
||||
if (region != null) {
|
||||
char[] placeholder = region.getPlaceholderText().toCharArray();
|
||||
for (char aPlaceholder : placeholder) {
|
||||
c = aPlaceholder;
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
if (x >= px) {
|
||||
break outer;
|
||||
}
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
column++;
|
||||
}
|
||||
|
||||
// Process 'after soft wrap' sign.
|
||||
offset = region.getEndOffset();
|
||||
}
|
||||
else {
|
||||
prevX = x;
|
||||
charWidth = mySoftWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
c = text.charAt(offset);
|
||||
charWidth = charToVisibleWidth(c, fontType, x);
|
||||
if (charWidth == 0) {
|
||||
break;
|
||||
}
|
||||
x += charWidth;
|
||||
|
||||
if (x >= px) {
|
||||
onSoftWrapDrawing = true;
|
||||
break outer;
|
||||
break;
|
||||
}
|
||||
column++;
|
||||
activeSoftWrapProcessed = true;
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
FoldRegion region = state.getCurrentFold();
|
||||
if (region != null) {
|
||||
char[] placeholder = region.getPlaceholderText().toCharArray();
|
||||
for (char aPlaceholder : placeholder) {
|
||||
c = aPlaceholder;
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
if (x >= px) {
|
||||
break outer;
|
||||
}
|
||||
column++;
|
||||
|
||||
if (charWidth < 0) {
|
||||
charWidth = EditorUtil.charWidth(c, fontType, this);
|
||||
}
|
||||
|
||||
if (charWidth < 0) {
|
||||
charWidth = spaceSize;
|
||||
}
|
||||
|
||||
if (x >= px && c == '\t' && !onSoftWrapDrawing) {
|
||||
if (mySettings.isCaretInsideTabs()) {
|
||||
column += (px - prevX) / spaceSize;
|
||||
if ((px - prevX) % spaceSize > spaceSize / 2) column++;
|
||||
}
|
||||
else if ((x - px) * 2 < x - prevX) {
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
}
|
||||
offset = region.getEndOffset();
|
||||
}
|
||||
else {
|
||||
prevX = x;
|
||||
c = text.charAt(offset);
|
||||
charWidth = charToVisibleWidth(c, fontType, x);
|
||||
if (charWidth == 0) {
|
||||
break;
|
||||
}
|
||||
x += charWidth;
|
||||
|
||||
if (x >= px) {
|
||||
break;
|
||||
if ((x - px) * 2 < charWidth) column++;
|
||||
}
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
if (charWidth < 0) {
|
||||
charWidth = EditorUtil.charWidth(c, fontType, this);
|
||||
}
|
||||
|
||||
if (charWidth < 0) {
|
||||
charWidth = spaceSize;
|
||||
}
|
||||
|
||||
if (x >= px && c == '\t' && !onSoftWrapDrawing) {
|
||||
if (mySettings.isCaretInsideTabs()) {
|
||||
column += (px - prevX) / spaceSize;
|
||||
if ((px - prevX) % spaceSize > spaceSize / 2) column++;
|
||||
}
|
||||
else if ((x - px) * 2 < x - prevX) {
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x >= px) {
|
||||
if ((x - px) * 2 < charWidth) column++;
|
||||
}
|
||||
else {
|
||||
int diff = px - x;
|
||||
column += diff / spaceSize;
|
||||
if (diff % spaceSize * 2 >= spaceSize) {
|
||||
column++;
|
||||
else {
|
||||
int diff = px - x;
|
||||
column += diff / spaceSize;
|
||||
if (diff % spaceSize * 2 >= spaceSize) {
|
||||
column++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new VisualPosition(line, column);
|
||||
return new VisualPosition(line, column);
|
||||
}
|
||||
finally {
|
||||
state.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1299,68 +1304,73 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
CharSequence text = myDocument.getCharsNoThreadCheck();
|
||||
int textLength = myDocument.getTextLength();
|
||||
IterationState state = new IterationState(this, startOffset, startOffset + length, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
try {
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
|
||||
int column = 0;
|
||||
outer:
|
||||
while (column < length) {
|
||||
if (offset >= textLength) break;
|
||||
int column = 0;
|
||||
outer:
|
||||
while (column < length) {
|
||||
if (offset >= textLength) break;
|
||||
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
// We need to consider 'before soft wrap drawing'.
|
||||
SoftWrap softWrap = getSoftWrapModel().getSoftWrap(offset);
|
||||
if (softWrap != null && offset > startOffset) {
|
||||
column++;
|
||||
x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
// Assuming that first soft wrap symbol is line feed or all soft wrap symbols before the first line feed are spaces.
|
||||
break;
|
||||
}
|
||||
|
||||
FoldRegion region = state.getCurrentFold();
|
||||
|
||||
if (region != null) {
|
||||
char[] placeholder = region.getPlaceholderText().toCharArray();
|
||||
for (char aPlaceholder : placeholder) {
|
||||
x += EditorUtil.charWidth(aPlaceholder, fontType, this);
|
||||
column++;
|
||||
if (column >= length) break outer;
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
offset = region.getEndOffset();
|
||||
}
|
||||
else {
|
||||
char c = text.charAt(offset);
|
||||
if (c == '\n') {
|
||||
// We need to consider 'before soft wrap drawing'.
|
||||
SoftWrap softWrap = getSoftWrapModel().getSoftWrap(offset);
|
||||
if (softWrap != null && offset > startOffset) {
|
||||
column++;
|
||||
x += getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
// Assuming that first soft wrap symbol is line feed or all soft wrap symbols before the first line feed are spaces.
|
||||
break;
|
||||
}
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = EditorUtil.nextTabStop(x, this);
|
||||
int columnDiff = (x - prevX) / spaceSize;
|
||||
if ((x - prevX) % spaceSize > 0) {
|
||||
// There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at
|
||||
// soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented
|
||||
// as a separate visual column may take less space than space width.
|
||||
columnDiff++;
|
||||
|
||||
FoldRegion region = state.getCurrentFold();
|
||||
|
||||
if (region != null) {
|
||||
char[] placeholder = region.getPlaceholderText().toCharArray();
|
||||
for (char aPlaceholder : placeholder) {
|
||||
x += EditorUtil.charWidth(aPlaceholder, fontType, this);
|
||||
column++;
|
||||
if (column >= length) break outer;
|
||||
}
|
||||
column += columnDiff;
|
||||
offset = region.getEndOffset();
|
||||
}
|
||||
else {
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
column++;
|
||||
char c = text.charAt(offset);
|
||||
if (c == '\n') {
|
||||
break;
|
||||
}
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = EditorUtil.nextTabStop(x, this);
|
||||
int columnDiff = (x - prevX) / spaceSize;
|
||||
if ((x - prevX) % spaceSize > 0) {
|
||||
// There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at
|
||||
// soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented
|
||||
// as a separate visual column may take less space than space width.
|
||||
columnDiff++;
|
||||
}
|
||||
column += columnDiff;
|
||||
}
|
||||
else {
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
column++;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
if (column != length) {
|
||||
x += EditorUtil.getSpaceWidth(fontType, this) * (length - column);
|
||||
}
|
||||
if (column != length) {
|
||||
x += EditorUtil.getSpaceWidth(fontType, this) * (length - column);
|
||||
}
|
||||
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
finally {
|
||||
state.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public int visibleLineToY(int line) {
|
||||
@@ -1910,7 +1920,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
int start = clipStartOffset;
|
||||
int end = clipEndOffset;
|
||||
getSoftWrapModel().registerSoftWrapsIfNecessary();
|
||||
IterationState iterationState = new IterationState(this, start, end, isPaintSelection());
|
||||
|
||||
LineIterator lIterator = createLineIterator();
|
||||
lIterator.start(start);
|
||||
@@ -1918,112 +1927,118 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return;
|
||||
}
|
||||
|
||||
TextAttributes attributes = iterationState.getMergedAttributes();
|
||||
Color backColor = getBackgroundColor(attributes);
|
||||
int fontType = attributes.getFontType();
|
||||
CharSequence text = myDocument.getCharsNoThreadCheck();
|
||||
int lastLineIndex = Math.max(0, myDocument.getLineCount() - 1);
|
||||
IterationState iterationState = new IterationState(this, start, end, isPaintSelection());
|
||||
try {
|
||||
TextAttributes attributes = iterationState.getMergedAttributes();
|
||||
Color backColor = getBackgroundColor(attributes);
|
||||
int fontType = attributes.getFontType();
|
||||
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 != null && !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.
|
||||
boolean[] caretRowPainted = new boolean[1];
|
||||
|
||||
while (!iterationState.atEnd() && !lIterator.atEnd()) {
|
||||
int hEnd = iterationState.getEndOffset();
|
||||
int lEnd = lIterator.getEnd();
|
||||
|
||||
if (hEnd >= lEnd) {
|
||||
FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
|
||||
if (collapsedFolderAt == null) {
|
||||
position.x = drawSoftWrapAwareBackground(g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
|
||||
defaultBackground, clip, softWrapsToSkip, caretRowPainted);
|
||||
|
||||
if (lIterator.getLineNumber() < lastLineIndex) {
|
||||
if (backColor != null && !backColor.equals(defaultBackground)) {
|
||||
g.setColor(backColor);
|
||||
g.fillRect(position.x, position.y, clip.x + clip.width - position.x, lineHeight);
|
||||
}
|
||||
}
|
||||
else {
|
||||
paintAfterFileEndBackground(iterationState,
|
||||
g,
|
||||
position, clip,
|
||||
lineHeight, defaultBackground, caretRowPainted);
|
||||
break;
|
||||
}
|
||||
|
||||
position.x = 0;
|
||||
if (position.y > clip.y + clip.height) break;
|
||||
position.y += lineHeight;
|
||||
start = lEnd;
|
||||
// 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 != null && !backColor.equals(defaultBackground)) {
|
||||
color = backColor;
|
||||
}
|
||||
|
||||
lIterator.advance();
|
||||
// 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();
|
||||
}
|
||||
else {
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
|
||||
if (softWrap != null) {
|
||||
position.x = drawSoftWrapAwareBackground(
|
||||
g, backColor, text, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, fontType,
|
||||
defaultBackground, clip, softWrapsToSkip, caretRowPainted
|
||||
);
|
||||
|
||||
// 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.
|
||||
boolean[] caretRowPainted = new boolean[1];
|
||||
|
||||
while (!iterationState.atEnd() && !lIterator.atEnd()) {
|
||||
int hEnd = iterationState.getEndOffset();
|
||||
int lEnd = lIterator.getEnd();
|
||||
|
||||
if (hEnd >= lEnd) {
|
||||
FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
|
||||
if (collapsedFolderAt == null) {
|
||||
position.x = drawSoftWrapAwareBackground(g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
|
||||
defaultBackground, clip, softWrapsToSkip, caretRowPainted);
|
||||
|
||||
if (lIterator.getLineNumber() < lastLineIndex) {
|
||||
if (backColor != null && !backColor.equals(defaultBackground)) {
|
||||
g.setColor(backColor);
|
||||
g.fillRect(position.x, position.y, clip.x + clip.width - position.x, lineHeight);
|
||||
}
|
||||
}
|
||||
else {
|
||||
paintAfterFileEndBackground(iterationState,
|
||||
g,
|
||||
position, clip,
|
||||
lineHeight, defaultBackground, caretRowPainted);
|
||||
break;
|
||||
}
|
||||
|
||||
position.x = 0;
|
||||
if (position.y > clip.y + clip.height) break;
|
||||
position.y += lineHeight;
|
||||
start = lEnd;
|
||||
}
|
||||
position.x = drawBackground(g, backColor, collapsedFolderAt.getPlaceholderText(), position, fontType, defaultBackground, clip);
|
||||
|
||||
lIterator.advance();
|
||||
}
|
||||
else {
|
||||
if (hEnd > lEnd - lIterator.getSeparatorLength()) {
|
||||
position.x = drawSoftWrapAwareBackground(
|
||||
g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
|
||||
defaultBackground, clip, softWrapsToSkip, caretRowPainted
|
||||
);
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
|
||||
if (softWrap != null) {
|
||||
position.x = drawSoftWrapAwareBackground(
|
||||
g, backColor, text, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, fontType,
|
||||
defaultBackground, clip, softWrapsToSkip, caretRowPainted
|
||||
);
|
||||
}
|
||||
position.x = drawBackground(g, backColor, collapsedFolderAt.getPlaceholderText(), position, fontType, defaultBackground, clip);
|
||||
}
|
||||
else {
|
||||
position.x = drawSoftWrapAwareBackground(
|
||||
g, backColor, text, start, hEnd, position, fontType, defaultBackground, clip, softWrapsToSkip, caretRowPainted
|
||||
);
|
||||
if (hEnd > lEnd - lIterator.getSeparatorLength()) {
|
||||
position.x = drawSoftWrapAwareBackground(
|
||||
g, backColor, text, start, lEnd - lIterator.getSeparatorLength(), position, fontType,
|
||||
defaultBackground, clip, softWrapsToSkip, caretRowPainted
|
||||
);
|
||||
}
|
||||
else {
|
||||
position.x = drawSoftWrapAwareBackground(
|
||||
g, backColor, text, start, hEnd, position, fontType, defaultBackground, clip, softWrapsToSkip, caretRowPainted
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterationState.advance();
|
||||
attributes = iterationState.getMergedAttributes();
|
||||
backColor = getBackgroundColor(attributes);
|
||||
fontType = attributes.getFontType();
|
||||
start = iterationState.getStartOffset();
|
||||
iterationState.advance();
|
||||
attributes = iterationState.getMergedAttributes();
|
||||
backColor = getBackgroundColor(attributes);
|
||||
fontType = attributes.getFontType();
|
||||
start = iterationState.getStartOffset();
|
||||
}
|
||||
}
|
||||
|
||||
flushBackground(g, clip);
|
||||
|
||||
if (lIterator.getLineNumber() >= lastLineIndex && position.y <= clip.y + clip.height) {
|
||||
paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground, caretRowPainted);
|
||||
}
|
||||
}
|
||||
|
||||
flushBackground(g, clip);
|
||||
|
||||
if (lIterator.getLineNumber() >= lastLineIndex && position.y <= clip.y + clip.height) {
|
||||
paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground, caretRowPainted);
|
||||
finally {
|
||||
iterationState.dispose();
|
||||
}
|
||||
|
||||
// Perform additional activity if soft wrap is added or removed during repainting.
|
||||
@@ -2356,92 +2371,97 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
return;
|
||||
}
|
||||
|
||||
IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection());
|
||||
LineIterator lIterator = createLineIterator();
|
||||
lIterator.start(start);
|
||||
if (lIterator.atEnd()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TextAttributes attributes = iterationState.getMergedAttributes();
|
||||
Color currentColor = attributes.getForegroundColor();
|
||||
if (currentColor == null) {
|
||||
currentColor = getForegroundColor();
|
||||
}
|
||||
Color effectColor = attributes.getEffectColor();
|
||||
EffectType effectType = attributes.getEffectType();
|
||||
int fontType = attributes.getFontType();
|
||||
g.setColor(currentColor);
|
||||
|
||||
final char[] chars = myDocument.getRawChars();
|
||||
|
||||
while (!iterationState.atEnd() && !lIterator.atEnd()) {
|
||||
int hEnd = iterationState.getEndOffset();
|
||||
int lEnd = lIterator.getEnd();
|
||||
if (hEnd >= lEnd) {
|
||||
FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
|
||||
if (collapsedFolderAt == null) {
|
||||
drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor,
|
||||
effectType, fontType, currentColor, logicalPosition);
|
||||
position.x = 0;
|
||||
if (position.y > clip.y + clip.height) {
|
||||
break;
|
||||
}
|
||||
position.y += lineHeight;
|
||||
start = lEnd;
|
||||
}
|
||||
|
||||
// myBorderEffect.eolReached(g, this);
|
||||
lIterator.advance();
|
||||
IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection());
|
||||
try {
|
||||
TextAttributes attributes = iterationState.getMergedAttributes();
|
||||
Color currentColor = attributes.getForegroundColor();
|
||||
if (currentColor == null) {
|
||||
currentColor = getForegroundColor();
|
||||
}
|
||||
else {
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
SoftWrap softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
|
||||
if (softWrap != null) {
|
||||
position.x = drawStringWithSoftWraps(
|
||||
g, chars, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, clip, effectColor, effectType,
|
||||
fontType, currentColor, logicalPosition
|
||||
);
|
||||
}
|
||||
int foldingXStart = position.x;
|
||||
position.x = drawString(
|
||||
g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor
|
||||
);
|
||||
//drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType,
|
||||
// fontType, currentColor, logicalPosition);
|
||||
BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, position.x, getLineHeight(), effectColor, effectType);
|
||||
Color effectColor = attributes.getEffectColor();
|
||||
EffectType effectType = attributes.getEffectType();
|
||||
int fontType = attributes.getFontType();
|
||||
g.setColor(currentColor);
|
||||
|
||||
final char[] chars = myDocument.getRawChars();
|
||||
|
||||
while (!iterationState.atEnd() && !lIterator.atEnd()) {
|
||||
int hEnd = iterationState.getEndOffset();
|
||||
int lEnd = lIterator.getEnd();
|
||||
if (hEnd >= lEnd) {
|
||||
FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
|
||||
if (collapsedFolderAt == null) {
|
||||
drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor,
|
||||
effectType, fontType, currentColor, logicalPosition);
|
||||
position.x = 0;
|
||||
if (position.y > clip.y + clip.height) {
|
||||
break;
|
||||
}
|
||||
position.y += lineHeight;
|
||||
start = lEnd;
|
||||
}
|
||||
|
||||
// myBorderEffect.eolReached(g, this);
|
||||
lIterator.advance();
|
||||
}
|
||||
else {
|
||||
position.x = drawStringWithSoftWraps(g, chars, start, Math.min(hEnd, lEnd - lIterator.getSeparatorLength()) , position, clip,
|
||||
effectColor, effectType, fontType, currentColor, logicalPosition);
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
SoftWrap softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
|
||||
if (softWrap != null) {
|
||||
position.x = drawStringWithSoftWraps(
|
||||
g, chars, collapsedFolderAt.getStartOffset(), collapsedFolderAt.getStartOffset(), position, clip, effectColor, effectType,
|
||||
fontType, currentColor, logicalPosition
|
||||
);
|
||||
}
|
||||
int foldingXStart = position.x;
|
||||
position.x = drawString(
|
||||
g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType, fontType, currentColor
|
||||
);
|
||||
//drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType,
|
||||
// fontType, currentColor, logicalPosition);
|
||||
BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, position.x, getLineHeight(), effectColor, effectType);
|
||||
|
||||
}
|
||||
else {
|
||||
position.x = drawStringWithSoftWraps(g, chars, start, Math.min(hEnd, lEnd - lIterator.getSeparatorLength()) , position, clip,
|
||||
effectColor, effectType, fontType, currentColor, logicalPosition);
|
||||
}
|
||||
|
||||
iterationState.advance();
|
||||
attributes = iterationState.getMergedAttributes();
|
||||
|
||||
currentColor = attributes.getForegroundColor();
|
||||
if (currentColor == null) {
|
||||
currentColor = getForegroundColor();
|
||||
}
|
||||
|
||||
effectColor = attributes.getEffectColor();
|
||||
effectType = attributes.getEffectType();
|
||||
fontType = attributes.getFontType();
|
||||
|
||||
start = iterationState.getStartOffset();
|
||||
}
|
||||
}
|
||||
|
||||
iterationState.advance();
|
||||
attributes = iterationState.getMergedAttributes();
|
||||
|
||||
currentColor = attributes.getForegroundColor();
|
||||
if (currentColor == null) {
|
||||
currentColor = getForegroundColor();
|
||||
}
|
||||
|
||||
effectColor = attributes.getEffectColor();
|
||||
effectType = attributes.getEffectType();
|
||||
fontType = attributes.getFontType();
|
||||
|
||||
start = iterationState.getStartOffset();
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
int foldingXStart = position.x;
|
||||
int foldingXEnd =
|
||||
drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType,
|
||||
fontType, currentColor, logicalPosition);
|
||||
BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, foldingXEnd, getLineHeight(), effectColor, effectType);
|
||||
// myBorderEffect.collapsedFolderReached(g, this);
|
||||
}
|
||||
}
|
||||
|
||||
FoldRegion collapsedFolderAt = iterationState.getCurrentFold();
|
||||
if (collapsedFolderAt != null) {
|
||||
int foldingXStart = position.x;
|
||||
int foldingXEnd =
|
||||
drawStringWithSoftWraps(g, collapsedFolderAt.getPlaceholderText(), position, clip, effectColor, effectType,
|
||||
fontType, currentColor, logicalPosition);
|
||||
BorderEffect.paintFoldedEffect(g, foldingXStart, position.y, foldingXEnd, getLineHeight(), effectColor, effectType);
|
||||
// myBorderEffect.collapsedFolderReached(g, this);
|
||||
finally {
|
||||
iterationState.dispose();
|
||||
}
|
||||
|
||||
flushCachedChars(g);
|
||||
@@ -2479,8 +2499,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
public String dumpState() {
|
||||
return "use soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off") + ", soft wraps data: " + getSoftWrapModel()
|
||||
+ "\n\nfolding data: " + getFoldingModel() + "\n\ndocument info: " + myDocument.dumpState();
|
||||
return "prefix: '" + (myPrefixText == null ? "none" : new String(myPrefixText))
|
||||
+ "', allow caret inside tab: " + mySettings.isCaretInsideTabs()
|
||||
+ ", allow caret after line end: " + mySettings.isVirtualSpace()
|
||||
+ ", soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off")
|
||||
+ ", soft wraps data: " + getSoftWrapModel()
|
||||
+ "\n\nfolding data: " + getFoldingModel()
|
||||
+ "\n\ndocument info: " + myDocument.dumpState();
|
||||
}
|
||||
|
||||
private class CachedFontContent {
|
||||
@@ -3305,6 +3330,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
while (start <= end) {
|
||||
i = (start + end) / 2;
|
||||
FoldRegion region = topLevelCollapsed[i];
|
||||
if (!region.isValid()) {
|
||||
// Folding model is inconsistent (update in progress).
|
||||
return null;
|
||||
}
|
||||
int regionVisualLine = offsetToVisualLine(region.getEndOffset() - 1);
|
||||
if (regionVisualLine < visualPos.line) {
|
||||
start = i + 1;
|
||||
@@ -5903,59 +5932,64 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
IterationState state = new IterationState(EditorImpl.this, offset, endOffset, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
try {
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
|
||||
int maxPreviousSoftWrappedWidth = -1;
|
||||
int maxPreviousSoftWrappedWidth = -1;
|
||||
|
||||
while (offset < documentLength && line < lineCount) {
|
||||
char c = text.charAt(offset);
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
while (softWrapsIndex < softWraps.size() && line < lineCount) {
|
||||
SoftWrap softWrap = softWraps.get(softWrapsIndex);
|
||||
if (softWrap.getStart() > offset) {
|
||||
break;
|
||||
while (offset < documentLength && line < lineCount) {
|
||||
char c = text.charAt(offset);
|
||||
if (offset >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
softWrapsIndex++;
|
||||
if (softWrap.getStart() == offset) {
|
||||
maxPreviousSoftWrappedWidth = Math.max(maxPreviousSoftWrappedWidth, x);
|
||||
x = softWrap.getIndentInPixels();
|
||||
|
||||
while (softWrapsIndex < softWraps.size() && line < lineCount) {
|
||||
SoftWrap softWrap = softWraps.get(softWrapsIndex);
|
||||
if (softWrap.getStart() > offset) {
|
||||
break;
|
||||
}
|
||||
softWrapsIndex++;
|
||||
if (softWrap.getStart() == offset) {
|
||||
maxPreviousSoftWrappedWidth = Math.max(maxPreviousSoftWrappedWidth, x);
|
||||
x = softWrap.getIndentInPixels();
|
||||
}
|
||||
}
|
||||
|
||||
FoldRegion collapsed = state.getCurrentFold();
|
||||
if (collapsed != null) {
|
||||
String placeholder = collapsed.getPlaceholderText();
|
||||
for (int i = 0; i < placeholder.length(); i++) {
|
||||
x += EditorUtil.charWidth(placeholder.charAt(i), fontType, EditorImpl.this);
|
||||
}
|
||||
offset = collapsed.getEndOffset();
|
||||
line = myDocument.getLineNumber(offset);
|
||||
}
|
||||
else if (c == '\t') {
|
||||
x = EditorUtil.nextTabStop(x, EditorImpl.this);
|
||||
offset++;
|
||||
}
|
||||
else if (c == '\n') {
|
||||
int width = Math.max(x, maxPreviousSoftWrappedWidth);
|
||||
myLineWidths.set(line, width);
|
||||
maxCalculatedLine = Math.max(maxCalculatedLine, line);
|
||||
if (line + 1 >= lineCount || myLineWidths.getQuick(line + 1) != -1) break;
|
||||
offset++;
|
||||
x = 0;
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
line++;
|
||||
if (line == lineCount - 1) {
|
||||
lastLineLengthCalculated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
x += ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName).charWidth(c, myEditorComponent);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
FoldRegion collapsed = state.getCurrentFold();
|
||||
if (collapsed != null) {
|
||||
String placeholder = collapsed.getPlaceholderText();
|
||||
for (int i = 0; i < placeholder.length(); i++) {
|
||||
x += EditorUtil.charWidth(placeholder.charAt(i), fontType, EditorImpl.this);
|
||||
}
|
||||
offset = collapsed.getEndOffset();
|
||||
line = myDocument.getLineNumber(offset);
|
||||
}
|
||||
else if (c == '\t') {
|
||||
x = EditorUtil.nextTabStop(x, EditorImpl.this);
|
||||
offset++;
|
||||
}
|
||||
else if (c == '\n') {
|
||||
int width = Math.max(x, maxPreviousSoftWrappedWidth);
|
||||
myLineWidths.set(line, width);
|
||||
maxCalculatedLine = Math.max(maxCalculatedLine, line);
|
||||
if (line + 1 >= lineCount || myLineWidths.getQuick(line + 1) != -1) break;
|
||||
offset++;
|
||||
x = 0;
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
line++;
|
||||
if (line == lineCount - 1) {
|
||||
lastLineLengthCalculated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
x += ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName).charWidth(c, myEditorComponent);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
state.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6011,35 +6045,40 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
@Override
|
||||
public int calcColumnNumber(@NotNull CharSequence text, int start, int offset, int tabSize) {
|
||||
IterationState state = new IterationState(this, start, start+offset, false);
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int column = 0;
|
||||
int x = 0;
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
for (int i = start; i < offset; i++) {
|
||||
if (i >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
try {
|
||||
int fontType = state.getMergedAttributes().getFontType();
|
||||
int column = 0;
|
||||
int x = 0;
|
||||
int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
|
||||
for (int i = start; i < offset; i++) {
|
||||
if (i >= state.getEndOffset()) {
|
||||
state.advance();
|
||||
fontType = state.getMergedAttributes().getFontType();
|
||||
}
|
||||
|
||||
SoftWrap softWrap = getSoftWrapModel().getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
column++; // For 'after soft wrap' drawing.
|
||||
x = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
}
|
||||
|
||||
char c = text.charAt(i);
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = EditorUtil.nextTabStop(x, this);
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
}
|
||||
else {
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
SoftWrap softWrap = getSoftWrapModel().getSoftWrap(i);
|
||||
if (softWrap != null) {
|
||||
column++; // For 'after soft wrap' drawing.
|
||||
x = getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
}
|
||||
|
||||
char c = text.charAt(i);
|
||||
if (c == '\t') {
|
||||
int prevX = x;
|
||||
x = EditorUtil.nextTabStop(x, this);
|
||||
column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
|
||||
}
|
||||
else {
|
||||
x += EditorUtil.charWidth(c, fontType, this);
|
||||
column++;
|
||||
}
|
||||
return column;
|
||||
}
|
||||
finally {
|
||||
state.dispose();
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.ex.DisposableIterator;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
import com.intellij.openapi.editor.ex.SweepProcessor;
|
||||
@@ -13,12 +14,9 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* This is mock implementation to be used in null-object pattern where necessary.
|
||||
* @author max
|
||||
@@ -126,8 +124,8 @@ public class EmptyMarkupModel implements MarkupModelEx {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
|
||||
return ContainerUtil.emptyIterator();
|
||||
public DisposableIterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
|
||||
return DisposableIterator.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,15 +35,13 @@ import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"ForLoopReplaceableByForEach"}) // Way too many garbage in AbstractList.iterator() produced otherwise.
|
||||
public final class IterationState {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.IterationState");
|
||||
private final TextAttributes myMergedAttributes = new TextAttributes();
|
||||
|
||||
private final HighlighterIterator myHighlighterIterator;
|
||||
private final HighlighterSweep myView = new HighlighterSweep();
|
||||
|
||||
private final HighlighterSweep myDoc = new HighlighterSweep();
|
||||
private final HighlighterSweep myView;
|
||||
private final HighlighterSweep myDoc;
|
||||
|
||||
private int myStartOffset;
|
||||
|
||||
@@ -71,6 +69,9 @@ public final class IterationState {
|
||||
private final EditorEx myEditor;
|
||||
private final Color myReadOnlyColor;
|
||||
|
||||
/**
|
||||
* You MUST CALL {@link #dispose()} afterwards
|
||||
*/
|
||||
public IterationState(@NotNull EditorEx editor, int start, int end, boolean useCaretAndSelection) {
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
myDocument = (DocumentEx)editor.getDocument();
|
||||
@@ -104,22 +105,29 @@ public final class IterationState {
|
||||
myCurrentHighlighters = new ArrayList<RangeHighlighterEx>();
|
||||
|
||||
MarkupModelEx editorMarkup = (MarkupModelEx)editor.getMarkupModel();
|
||||
myView.init(editorMarkup, start, myEnd);
|
||||
myView = new HighlighterSweep(editorMarkup, start, myEnd);
|
||||
|
||||
final MarkupModelEx docMarkup = (MarkupModelEx)DocumentMarkupModel.forDocument(editor.getDocument(), editor.getProject(), true);
|
||||
myDoc.init(docMarkup, start, myEnd);
|
||||
myDoc = new HighlighterSweep(docMarkup, start, myEnd);
|
||||
|
||||
myEndOffset = myStartOffset;
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
private class HighlighterSweep {
|
||||
private RangeHighlighterEx myNextHighlighter = null;
|
||||
private PushBackIterator<RangeHighlighterEx> myIterator;
|
||||
public void dispose() {
|
||||
myView.dispose();
|
||||
myDoc.dispose();
|
||||
}
|
||||
|
||||
private void init(@NotNull MarkupModelEx markupModel, int start, int end) {
|
||||
myIterator = new PushBackIterator<RangeHighlighterEx>(markupModel.overlappingIterator(start, end));
|
||||
private class HighlighterSweep {
|
||||
private RangeHighlighterEx myNextHighlighter;
|
||||
private final PushBackIterator<RangeHighlighterEx> myIterator;
|
||||
private final DisposableIterator<RangeHighlighterEx> myDisposableIterator;
|
||||
|
||||
private HighlighterSweep(@NotNull MarkupModelEx markupModel, int start, int end) {
|
||||
myDisposableIterator = markupModel.overlappingIterator(start, end);
|
||||
myIterator = new PushBackIterator<RangeHighlighterEx>(myDisposableIterator);
|
||||
int skipped = 0;
|
||||
while (myIterator.hasNext()) {
|
||||
RangeHighlighterEx highlighter = myIterator.next();
|
||||
@@ -176,6 +184,10 @@ public final class IterationState {
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myDisposableIterator.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean skipHighlighter(@NotNull RangeHighlighterEx highlighter) {
|
||||
@@ -230,6 +242,7 @@ public final class IterationState {
|
||||
private int getGuardedBlockEnd(int start) {
|
||||
List<RangeMarker> blocks = myDocument.getGuardedBlocks();
|
||||
int min = myEnd;
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < blocks.size(); i++) {
|
||||
RangeMarker block = blocks.get(i);
|
||||
if (block.getStartOffset() > start) {
|
||||
@@ -257,7 +270,6 @@ public final class IterationState {
|
||||
|
||||
private void advanceSegmentHighlighters() {
|
||||
myDoc.advance();
|
||||
|
||||
myView.advance();
|
||||
|
||||
for (int i = myCurrentHighlighters.size() - 1; i >= 0; i--) {
|
||||
@@ -296,6 +308,7 @@ public final class IterationState {
|
||||
private int getMinSegmentHighlightersEnd() {
|
||||
int end = myEnd;
|
||||
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < myCurrentHighlighters.size(); i++) {
|
||||
RangeHighlighterEx highlighter = myCurrentHighlighters.get(i);
|
||||
if (highlighter.getAffectedAreaEndOffset() < end) {
|
||||
@@ -332,6 +345,7 @@ public final class IterationState {
|
||||
ContainerUtil.quickSort(myCurrentHighlighters, LayerComparator.INSTANCE);
|
||||
}
|
||||
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < size; i++) {
|
||||
RangeHighlighterEx highlighter = myCurrentHighlighters.get(i);
|
||||
if (highlighter.getTextAttributes() == TextAttributes.ERASE_MARKER) {
|
||||
@@ -342,6 +356,7 @@ public final class IterationState {
|
||||
List<TextAttributes> cachedAttributes = myCachedAttributesList;
|
||||
cachedAttributes.clear();
|
||||
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < size; i++) {
|
||||
RangeHighlighterEx highlighter = myCurrentHighlighters.get(i);
|
||||
if (selection != null && highlighter.getLayer() < HighlighterLayer.SELECTION) {
|
||||
@@ -387,6 +402,7 @@ public final class IterationState {
|
||||
EffectType effectType = null;
|
||||
int fontType = 0;
|
||||
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < cachedAttributes.size(); i++) {
|
||||
TextAttributes attrs = cachedAttributes.get(i);
|
||||
|
||||
@@ -453,6 +469,7 @@ public final class IterationState {
|
||||
|
||||
ContainerUtil.quickSort(myCurrentHighlighters, LayerComparator.INSTANCE);
|
||||
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < myCurrentHighlighters.size(); i++) {
|
||||
RangeHighlighterEx highlighter = myCurrentHighlighters.get(i);
|
||||
if (caret != null && highlighter.getLayer() < HighlighterLayer.CARET_ROW) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.ex.DisposableIterator;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
|
||||
import com.intellij.openapi.editor.ex.SweepProcessor;
|
||||
@@ -45,7 +46,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx {
|
||||
@@ -257,7 +257,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Iterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
|
||||
public DisposableIterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
|
||||
return myHighlighterTree.overlappingIterator(startOffset, endOffset);
|
||||
}
|
||||
|
||||
|
||||
+48
-43
@@ -208,51 +208,56 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
|
||||
myContext.text = document.getCharsSequence();
|
||||
myContext.tokenStartOffset = start;
|
||||
IterationState iterationState = new IterationState(myEditor, start, document.getTextLength(), false);
|
||||
TextAttributes attributes = iterationState.getMergedAttributes();
|
||||
myContext.fontType = attributes.getFontType();
|
||||
myContext.rangeEndOffset = event.getNewEndOffset();
|
||||
|
||||
EditorPosition position = new EditorPosition(logical, start, myEditor, myRepresentationHelper);
|
||||
Point point = myEditor.visualPositionToXY(visual);
|
||||
position.x = point.x;
|
||||
int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor);
|
||||
|
||||
myContext.logicalLineData.update(logical.line, spaceWidth, myEditor);
|
||||
|
||||
myContext.currentPosition = position;
|
||||
myContext.lineStartPosition = position.clone();
|
||||
myContext.fontType2spaceWidth.put(myContext.fontType, spaceWidth);
|
||||
myContext.softWrapStartOffset = position.offset;
|
||||
|
||||
myContext.contentComponent = myEditor.getContentComponent();
|
||||
myContext.reservedWidthInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
|
||||
// Perform soft wraps calculation.
|
||||
while (!iterationState.atEnd() && myContext.currentPosition.offset <= event.getNewEndOffset()) {
|
||||
FoldRegion currentFold = iterationState.getCurrentFold();
|
||||
if (currentFold == null) {
|
||||
myContext.tokenEndOffset = iterationState.getEndOffset();
|
||||
processNonFoldToken();
|
||||
}
|
||||
else {
|
||||
boolean continueProcessing = processCollapsedFoldRegion(currentFold);
|
||||
if (!continueProcessing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'myOffset2widthInPixels' contains information necessary to processing soft wraps that lay before the current offset.
|
||||
// We do know that soft wraps are not allowed to go backward after processed collapsed fold region, hence, we drop
|
||||
// information about processed symbols width.
|
||||
myOffset2widthInPixels.clear();
|
||||
}
|
||||
|
||||
iterationState.advance();
|
||||
attributes = iterationState.getMergedAttributes();
|
||||
try {
|
||||
TextAttributes attributes = iterationState.getMergedAttributes();
|
||||
myContext.fontType = attributes.getFontType();
|
||||
myContext.tokenStartOffset = iterationState.getStartOffset();
|
||||
myOffset2fontType.fill(myContext.tokenStartOffset, iterationState.getEndOffset(), myContext.fontType);
|
||||
myContext.rangeEndOffset = event.getNewEndOffset();
|
||||
|
||||
EditorPosition position = new EditorPosition(logical, start, myEditor, myRepresentationHelper);
|
||||
Point point = myEditor.visualPositionToXY(visual);
|
||||
position.x = point.x;
|
||||
int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor);
|
||||
|
||||
myContext.logicalLineData.update(logical.line, spaceWidth, myEditor);
|
||||
|
||||
myContext.currentPosition = position;
|
||||
myContext.lineStartPosition = position.clone();
|
||||
myContext.fontType2spaceWidth.put(myContext.fontType, spaceWidth);
|
||||
myContext.softWrapStartOffset = position.offset;
|
||||
|
||||
myContext.contentComponent = myEditor.getContentComponent();
|
||||
myContext.reservedWidthInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
|
||||
|
||||
// Perform soft wraps calculation.
|
||||
while (!iterationState.atEnd() && myContext.currentPosition.offset <= event.getNewEndOffset()) {
|
||||
FoldRegion currentFold = iterationState.getCurrentFold();
|
||||
if (currentFold == null) {
|
||||
myContext.tokenEndOffset = iterationState.getEndOffset();
|
||||
processNonFoldToken();
|
||||
}
|
||||
else {
|
||||
boolean continueProcessing = processCollapsedFoldRegion(currentFold);
|
||||
if (!continueProcessing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'myOffset2widthInPixels' contains information necessary to processing soft wraps that lay before the current offset.
|
||||
// We do know that soft wraps are not allowed to go backward after processed collapsed fold region, hence, we drop
|
||||
// information about processed symbols width.
|
||||
myOffset2widthInPixels.clear();
|
||||
}
|
||||
|
||||
iterationState.advance();
|
||||
attributes = iterationState.getMergedAttributes();
|
||||
myContext.fontType = attributes.getFontType();
|
||||
myContext.tokenStartOffset = iterationState.getStartOffset();
|
||||
myOffset2fontType.fill(myContext.tokenStartOffset, iterationState.getEndOffset(), myContext.fontType);
|
||||
}
|
||||
notifyListenersOnVisualLineEnd();
|
||||
}
|
||||
finally {
|
||||
iterationState.dispose();
|
||||
}
|
||||
notifyListenersOnVisualLineEnd();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
<xy x="63" y="44" width="604" height="510"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="etched"/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="6b492" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
@@ -52,7 +52,7 @@
|
||||
<properties>
|
||||
<contentType value="text/html"/>
|
||||
<maximumSize width="2147483647" height="25"/>
|
||||
<text value="<html> <head> </head> <body> </body> </html> "/>
|
||||
<text value="<html> <head> </head> <body> <p style="margin-top: 0"> </p> </body> </html> "/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="bf1d9">
|
||||
|
||||
@@ -53,7 +53,7 @@ class BaseLabel extends JLabel {
|
||||
|
||||
private void updateFont() {
|
||||
Font f = UIUtil.getLabelFont();
|
||||
Font baseFont = f.deriveFont(f.getStyle(), Math.max(11, f.getSize() - 1));
|
||||
Font baseFont = f.deriveFont(f.getStyle(), Math.max(11, f.getSize() - 2));
|
||||
if (myBold) {
|
||||
setFont(baseFont.deriveFont(Font.BOLD));
|
||||
}
|
||||
|
||||
-1
@@ -70,7 +70,6 @@ public class ToolWindowContentUi extends JPanel implements ContentUI, PropertyCh
|
||||
ContentLayout myComboLayout = new ComboContentLayout(this);
|
||||
|
||||
private ToolWindowContentUiType myType = ToolWindowContentUiType.TABBED;
|
||||
private DefaultActionGroup ourGroup;
|
||||
private static DefaultActionGroup myGroup;
|
||||
|
||||
public ToolWindowContentUi(ToolWindowImpl window) {
|
||||
|
||||
@@ -101,7 +101,7 @@ ide.tabbedPane.dragOutMultiplier=1.2
|
||||
|
||||
ide.mac.filechooser.showhidden.files=false
|
||||
ide.mac.filechooser.native=true
|
||||
ide.mac.message.dialogs.as.sheets=false
|
||||
ide.mac.message.dialogs.as.sheets=true
|
||||
ide.mac.inplaceDialogMnemonicsFix=true
|
||||
|
||||
debugger.valueTooltipAutoShow=true
|
||||
|
||||
@@ -457,6 +457,7 @@
|
||||
<selectInTarget implementation="com.intellij.ide.navigationToolbar.SelectInNavBarTarget"/>
|
||||
<selectInTarget implementation="com.intellij.ide.impl.StructureViewSelectInTarget"/>
|
||||
<selectInTarget implementation="com.intellij.ide.impl.ProjectViewSelectInExplorerTarget"/>
|
||||
<selectInTarget implementation="com.intellij.ide.favoritesTreeView.FavoritesViewSelectInTarget"/>
|
||||
|
||||
<elementLookupRenderer implementation="com.intellij.codeInsight.template.impl.TemplateLookupRenderer"/>
|
||||
|
||||
@@ -653,6 +654,7 @@
|
||||
<fileIconProvider implementation="com.intellij.ide.FileIconPatcherImpl"/>
|
||||
<renameHandler implementation="com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler"/>
|
||||
<renameHandler implementation="com.intellij.refactoring.rename.inplace.MemberInplaceRenameHandler"/>
|
||||
<completion.contributor language="any" implementationClass="com.intellij.refactoring.rename.inplace.CompletionContributorForInplaceRename" order="first"/>
|
||||
|
||||
<projectService serviceInterface="com.intellij.openapi.vcs.changes.ui.ChangesFileNameDecorator"
|
||||
serviceImplementation="com.intellij.openapi.vcs.changes.ui.WolfChangesFileNameDecorator"/>
|
||||
|
||||
@@ -1655,6 +1655,32 @@ public class StringUtil {
|
||||
idx += 2;
|
||||
}
|
||||
}
|
||||
|
||||
public static String unescapeSlashes(@NotNull final String str) {
|
||||
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
unescapeSlashes(buf, str);
|
||||
return buf.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(buf);
|
||||
}
|
||||
}
|
||||
|
||||
private static void unescapeSlashes(StringBuilder buf, String str) {
|
||||
final int length = str.length();
|
||||
final int last = length - 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
char ch = str.charAt(i);
|
||||
if (ch == '\\' && i != last) {
|
||||
i++;
|
||||
ch = str.charAt(i);
|
||||
if (ch != '/') buf.append('\\');
|
||||
}
|
||||
|
||||
buf.append(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public static void quote(@NotNull final StringBuilder builder) {
|
||||
quote(builder, '\"');
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package com.intellij.util.containers;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Queue<T> {
|
||||
private final static Object[] EMPTY = new Object[0];
|
||||
private Object[] myArray;
|
||||
private int myFirst;
|
||||
private int myLast;
|
||||
@@ -29,7 +30,7 @@ public class Queue<T> {
|
||||
private boolean isWrapped;
|
||||
|
||||
public Queue(int initialCapacity) {
|
||||
myArray = initialCapacity > 0 ? new Object[initialCapacity] : EMPTY;
|
||||
myArray = initialCapacity > 0 ? new Object[initialCapacity] : ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
|
||||
public void addLast(T object) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
|
||||
@@ -25,6 +26,8 @@ import java.io.*;
|
||||
* @author max
|
||||
*/
|
||||
public class SafeFileOutputStream extends OutputStream {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.SafeFileOutputStream");
|
||||
|
||||
private final File myTargetFile;
|
||||
private final boolean myPreserveAttributes;
|
||||
private final OutputStream myBackDoorStream;
|
||||
@@ -51,6 +54,7 @@ public class SafeFileOutputStream extends OutputStream {
|
||||
myBackDoorStream.write(b);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
failed = true;
|
||||
throw e;
|
||||
}
|
||||
@@ -61,6 +65,7 @@ public class SafeFileOutputStream extends OutputStream {
|
||||
myBackDoorStream.write(b);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
failed = true;
|
||||
throw e;
|
||||
}
|
||||
@@ -72,6 +77,7 @@ public class SafeFileOutputStream extends OutputStream {
|
||||
myBackDoorStream.write(b, off, len);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
failed = true;
|
||||
throw e;
|
||||
}
|
||||
@@ -83,6 +89,7 @@ public class SafeFileOutputStream extends OutputStream {
|
||||
myBackDoorStream.flush();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
failed = true;
|
||||
throw e;
|
||||
}
|
||||
@@ -94,13 +101,18 @@ public class SafeFileOutputStream extends OutputStream {
|
||||
myBackDoorStream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
FileUtil.delete(backdoorFile());
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
throw new IOException("Failed to save to backup file (" + backdoorFile() + "). Original file (" + myTargetFile + ") left unchanged.");
|
||||
}
|
||||
|
||||
final int permissions = myPreserveAttributes ? FileSystemUtil.getPermissions(myTargetFile) : -1;
|
||||
if (failed || !FileUtil.delete(myTargetFile)) {
|
||||
throw new IOException("Failed to save to " + myTargetFile + ". No data were harmed. Attempt result left at " + backdoorFile());
|
||||
if (!FileUtil.delete(myTargetFile) && myTargetFile.exists()) {
|
||||
throw new IOException("Failed to save to " + myTargetFile + ". The file left unchanged. Attempt result stored to " + backdoorFile());
|
||||
}
|
||||
|
||||
FileUtil.rename(backdoorFile(), myTargetFile);
|
||||
|
||||
@@ -48,6 +48,15 @@ public class QueueTest extends TestCase {
|
||||
testEmpty();
|
||||
}
|
||||
|
||||
public void testQuibble() {
|
||||
com.intellij.util.containers.Queue queue = new com.intellij.util.containers.Queue(0);
|
||||
String xxx = "xxx";
|
||||
queue.addLast(xxx);
|
||||
CHECK.compareAll(queue.toArray(), new String[] {xxx});
|
||||
Object x = queue.pullFirst();
|
||||
assertEquals(xxx,x);
|
||||
assertTrue(queue.isEmpty());
|
||||
}
|
||||
public void testCycling() {
|
||||
com.intellij.util.containers.Queue queue = new com.intellij.util.containers.Queue(10);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
|
||||
@@ -234,6 +234,10 @@ public abstract class AndroidLogcatToolWindowView implements Disposable {
|
||||
myFiltersList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String filterName = (String)myFiltersList.getSelectedValue();
|
||||
final ConfiguredFilter filter = filterName != null ? compileConfiguredFilter(filterName) : null;
|
||||
|
||||
|
||||
@@ -289,6 +289,7 @@ public class AndroidModuleBuilder extends JavaModuleBuilder {
|
||||
if (contentRoot.findChild(SdkConstants.FN_ANDROID_MANIFEST_XML) == null) {
|
||||
AndroidUtils.printMessageToConsole(project, "The project wasn't generated by 'android' tool.",
|
||||
ConsoleViewContentType.ERROR_OUTPUT);
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
|
||||
@@ -68,7 +68,7 @@ public class GitPull extends GitRepositoryAction {
|
||||
final Label beforeLabel = LocalHistory.getInstance().putSystemLabel(project, "Before update");
|
||||
|
||||
final AtomicReference<GitLineHandler> handlerReference = new AtomicReference<GitLineHandler>();
|
||||
new Task.Modal(project, GitBundle.message("pulling.title", dialog.getRemote()), false) {
|
||||
new Task.Modal(project, GitBundle.message("pulling.title", dialog.getRemote()), true) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
GitRepository repository = GitRepositoryManager.getInstance(project).getRepositoryForRoot(dialog.gitRoot());
|
||||
@@ -103,8 +103,9 @@ public class GitPull extends GitRepositoryAction {
|
||||
final GitRevisionNumber currentRev = new GitRevisionNumber(revision);
|
||||
|
||||
GitTask pullTask = new GitTask(project, handlerReference.get(), GitBundle.message("pulling.title", dialog.getRemote()));
|
||||
pullTask.setProgressIndicator(indicator);
|
||||
pullTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());
|
||||
pullTask.executeModal(new GitTaskResultHandlerAdapter() {
|
||||
pullTask.execute(true, false, new GitTaskResultHandlerAdapter() {
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
GitMergeUtil.showUpdates(GitPull.this, project, exceptions, root, currentRev, beforeLabel, getActionName(), ActionInfo.UPDATE);
|
||||
|
||||
@@ -159,7 +159,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
h.endOptions();
|
||||
h.addRelativePaths(repositoryFilePath);
|
||||
String output = h.run();
|
||||
GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null);
|
||||
GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null, revision == null ? null : revision.getRevisionNumber());
|
||||
class CommitInfo {
|
||||
Date date;
|
||||
String author;
|
||||
@@ -228,7 +228,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
String annotatedContent,
|
||||
boolean forCurrentRevision, VcsRevisionNumber revisionNumber) {
|
||||
final GitFileAnnotation gitFileAnnotation =
|
||||
new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), forCurrentRevision);
|
||||
new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), forCurrentRevision, revisionNumber);
|
||||
gitFileAnnotation.addLogEntries(session.getRevisionList());
|
||||
final VcsLineAnnotationData basicAnnotation = vcsAnnotation.getBasicAnnotation();
|
||||
final int size = basicAnnotation.getNumLines();
|
||||
|
||||
@@ -57,6 +57,7 @@ public class GitFileAnnotation implements FileAnnotation {
|
||||
* The project reference
|
||||
*/
|
||||
private final Project myProject;
|
||||
private final VcsRevisionNumber myBaseRevision;
|
||||
/**
|
||||
* Annotation change listeners
|
||||
*/
|
||||
@@ -103,6 +104,7 @@ public class GitFileAnnotation implements FileAnnotation {
|
||||
return author == null ? "" : author;
|
||||
}
|
||||
};
|
||||
private final GitVcs myVcs;
|
||||
|
||||
/**
|
||||
* A constructor
|
||||
@@ -110,10 +112,13 @@ public class GitFileAnnotation implements FileAnnotation {
|
||||
* @param project the project of annotation provider
|
||||
* @param file the git root
|
||||
* @param monitorFlag if false the file system will not be listened for changes (used for annotated files from the repository).
|
||||
* @param revision
|
||||
*/
|
||||
public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, final boolean monitorFlag) {
|
||||
public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, final boolean monitorFlag, final VcsRevisionNumber revision) {
|
||||
myProject = project;
|
||||
myVcs = GitVcs.getInstance(myProject);
|
||||
myFile = file;
|
||||
myBaseRevision = revision == null ? (myVcs.getDiffProvider().getCurrentRevision(file)) : revision;
|
||||
myMonitorFlag = monitorFlag;
|
||||
if (myMonitorFlag) {
|
||||
myFileListener = new VirtualFileAdapter() {
|
||||
@@ -121,6 +126,8 @@ public class GitFileAnnotation implements FileAnnotation {
|
||||
public void contentsChanged(final VirtualFileEvent event) {
|
||||
if (myFile != event.getFile()) return;
|
||||
if (!event.isFromRefresh()) return;
|
||||
final VcsRevisionNumber currentRevision = myVcs.getDiffProvider().getCurrentRevision(myFile);
|
||||
if (currentRevision != null && currentRevision.equals(revision)) return;
|
||||
fireAnnotationChanged();
|
||||
}
|
||||
};
|
||||
@@ -391,6 +398,11 @@ public class GitFileAnnotation implements FileAnnotation {
|
||||
private void checkAndFire() {
|
||||
// for the case of commit changes... remove annotation gutter
|
||||
if (FileStatus.NOT_CHANGED.equals(FileStatusManager.getInstance(myProject).getStatus(myFile))) {
|
||||
if (myBaseRevision != null) {
|
||||
final VcsRevisionNumber currentRevision = myVcs.getDiffProvider().getCurrentRevision(myFile);
|
||||
// revision is not when monitorFlag is true
|
||||
if (currentRevision != null && currentRevision.equals(myBaseRevision)) return;
|
||||
}
|
||||
fireAnnotationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +252,8 @@
|
||||
<weigher key="proximity" implementationClass="org.jetbrains.plugins.groovy.lang.completion.weighers.GrReferenceListWeigher"
|
||||
id="groovyReferenceListWeigher" order="before openedInEditor" />
|
||||
|
||||
<topLevelClassProvider implementation="org.jetbrains.plugins.groovy.debugger.GroovyTopLevelParentClassProvider"/>
|
||||
|
||||
<debuggerClassFilterProvider implementation="org.jetbrains.plugins.groovy.debugger.filters.GroovyDebuggerClassFilterProvider"/>
|
||||
|
||||
<useScopeEnlarger implementation="org.jetbrains.plugins.groovy.lang.psi.impl.search.GrPrivateFieldScopeEnlarger"/>
|
||||
|
||||
+5
-5
@@ -94,8 +94,8 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory {
|
||||
javaText.append("groovy.lang.MetaClass |mc;\n");
|
||||
javaText.append("java.lang.Class |clazz;\n");
|
||||
if (!isStatic) {
|
||||
javaText.append("|clazz = ((java.lang.Object)this).getClass();\n");
|
||||
javaText.append("|mc = ((groovy.lang.GroovyObject)this).getMetaClass();\n");
|
||||
javaText.append("|clazz = this.getClass();\n");
|
||||
javaText.append("|mc = this.getMetaClass();\n");
|
||||
} else {
|
||||
assert contextClass != null;
|
||||
javaText.append("|clazz = java.lang.Class.forName(\"").append(contextClass.getQualifiedName()).append("\");\n");
|
||||
@@ -118,16 +118,16 @@ public class GroovyCodeFragmentFactory implements CodeFragmentFactory {
|
||||
javaText.append("groovy.lang.ExpandoMetaClass |emc = new groovy.lang.ExpandoMetaClass(|clazz);\n");
|
||||
if (!isStatic) {
|
||||
javaText.append("|emc.setProperty(\"").append(EVAL_NAME).append("\", |closure);\n");
|
||||
javaText.append("((groovy.lang.GroovyObject)this).setMetaClass(|emc);\n");
|
||||
javaText.append("this.setMetaClass(|emc);\n");
|
||||
} else {
|
||||
javaText.append("((groovy.lang.GroovyObject)|emc.getProperty(\"static\")).setProperty(\"").append(EVAL_NAME).append("\", |closure);\n");
|
||||
javaText.append("|emc.getProperty(\"static\").setProperty(\"").append(EVAL_NAME).append("\", |closure);\n");
|
||||
javaText.append("groovy.lang.GroovySystem.getMetaClassRegistry().setMetaClass(|clazz, |emc);\n");
|
||||
}
|
||||
javaText.append("|emc.initialize();\n");
|
||||
javaText.append(unwrapVals(values));
|
||||
if (!isStatic) {
|
||||
javaText.append("java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeMethod(this, \"").append(EVAL_NAME).append("\", |resVals);\n");
|
||||
javaText.append("((groovy.lang.GroovyObject)this).setMetaClass(|mc);"); //try/finally is not supported
|
||||
javaText.append("this.setMetaClass(|mc);"); //try/finally is not supported
|
||||
} else {
|
||||
javaText.append("java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeStaticMethod(|clazz, \"").append(EVAL_NAME).append("\", |resVals);\n");
|
||||
javaText.append("groovy.lang.GroovySystem.getMetaClassRegistry().setMetaClass(|clazz, |mc);\n");
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.debugger;
|
||||
|
||||
import com.intellij.debugger.engine.TopLevelParentClassProvider;
|
||||
import com.intellij.psi.PsiAnonymousClass;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GroovyTopLevelParentClassProvider extends TopLevelParentClassProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiClass getCustomTopLevelParentClass(PsiClass psiClass) {
|
||||
if (!(psiClass instanceof GrTypeDefinition)) return null;
|
||||
|
||||
PsiClass enclosing = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class, true);
|
||||
while (enclosing != null) {
|
||||
psiClass = enclosing;
|
||||
enclosing = PsiTreeUtil.getParentOfType(enclosing, PsiClass.class, true);
|
||||
}
|
||||
|
||||
if (psiClass instanceof PsiAnonymousClass) {
|
||||
final PsiFile file = psiClass.getContainingFile();
|
||||
if (file instanceof GroovyFile) {
|
||||
return ((GroovyFile)file).getScriptClass();
|
||||
}
|
||||
}
|
||||
|
||||
return psiClass;
|
||||
}
|
||||
}
|
||||
+19
-1
@@ -64,7 +64,12 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce
|
||||
IElementType tokenType = token.getNode().getElementType();
|
||||
|
||||
if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) {
|
||||
return StringUtil.escapeSlashes(s);
|
||||
if (escapeSlashes) {
|
||||
return StringUtil.escapeSlashes(s);
|
||||
}
|
||||
else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
String chars;
|
||||
@@ -87,4 +92,17 @@ public class GroovyLiteralCopyPasteProcessor extends StringLiteralCopyPasteProce
|
||||
StringUtil.escapeStringCharacters(s.length(), s, chars, escapeSlashes, buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String unescape(String text, PsiElement token) {
|
||||
final IElementType tokenType = token.getNode().getElementType();
|
||||
|
||||
if (tokenType == mREGEX_CONTENT || tokenType == mREGEX_LITERAL) {
|
||||
return StringUtil.unescapeSlashes(text);
|
||||
}
|
||||
|
||||
return super.unescape(text, token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -23,4 +23,5 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
|
||||
* @author ilyas
|
||||
*/
|
||||
public interface GrLiteral extends GrExpression, PsiLiteral {
|
||||
void setStringValue(String value);
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.GroovyStringLiteralManipulator;
|
||||
|
||||
|
||||
public abstract class GrAbstractLiteral extends GrExpressionImpl implements GrLiteral {
|
||||
|
||||
public GrAbstractLiteral(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStringValue(String value) {
|
||||
new GroovyStringLiteralManipulator().handleContentChange(this, value);
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -43,7 +43,7 @@ import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GrLiteralImpl extends GrExpressionImpl implements GrLiteral, PsiLanguageInjectionHost {
|
||||
public class GrLiteralImpl extends GrAbstractLiteral implements GrLiteral, PsiLanguageInjectionHost {
|
||||
|
||||
private static final Function<GrLiteralImpl,PsiType> TYPE_CALCULATOR = new NullableFunction<GrLiteralImpl, PsiType>() {
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ import java.util.List;
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public class GrStringImpl extends GrExpressionImpl implements GrString {
|
||||
public class GrStringImpl extends GrAbstractLiteral implements GrString {
|
||||
private static final Function<GrStringImpl,PsiType> TYPE_CALCULATOR = new Function<GrStringImpl, PsiType>() {
|
||||
@Override
|
||||
public PsiType fun(GrStringImpl grString) {
|
||||
|
||||
@@ -25,39 +25,6 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
class GroovyCopyPasteTest extends LightCodeInsightFixtureTestCase {
|
||||
int myAddImportsOld
|
||||
|
||||
public void testEscapeSlashesInRegex() {
|
||||
myFixture.configureByText 'a.groovy', '<selection>a/b</selection>'
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', 'def x = /smth<caret>/'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult 'def x = /smtha\\/b<caret>/'
|
||||
}
|
||||
|
||||
public void testEscapeSlashesInRegexFromRegex() {
|
||||
myFixture.configureByText 'a.groovy', 'def x = /<selection>a\\/b</selection>/'
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', 'def x = /smth<caret>/'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult 'def x = /smtha\\/b<caret>/'
|
||||
}
|
||||
|
||||
void testDontEscapeSymbolsInRegex(){
|
||||
myFixture.configureByText 'a.groovy', '''def x = <selection>a/b</selection>'''
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', 'def x = /<caret> /'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult '''def x = /a\\/b /'''
|
||||
}
|
||||
|
||||
public void testEscapeDollarInGString() {
|
||||
myFixture.configureByText 'a.groovy', '''def x = '<selection>$a</selection>b/'''
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', 'def x = "smth<caret>h"'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult 'def x = "smth$a<caret>h"'
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -73,41 +40,64 @@ class GroovyCopyPasteTest extends LightCodeInsightFixtureTestCase {
|
||||
settings.ADD_IMPORTS_ON_PASTE = myAddImportsOld;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void doTest(String fromFileName, String fromText, String toText, String expected) {
|
||||
myFixture.configureByText fromFileName, fromText
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', toText
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult expected
|
||||
}
|
||||
|
||||
public void testEscapeSlashesInRegex() {
|
||||
doTest 'a.groovy', '<selection>a/b</selection>', 'def x = /smth<caret>/', 'def x = /smtha\\/b<caret>/'
|
||||
}
|
||||
|
||||
public void testEscapeSlashesInRegexFromRegex() {
|
||||
doTest 'a.groovy', 'def x = /<selection>a\\/b</selection>/', 'def x = /smth<caret>/', 'def x = /smtha\\/b<caret>/'
|
||||
}
|
||||
|
||||
void testDontEscapeSymbolsInRegex(){
|
||||
doTest 'a.groovy', '''def x = <selection>a/b</selection>''', 'def x = /<caret> /', '''def x = /a\\/b /'''
|
||||
}
|
||||
|
||||
public void testEscapeDollarInGString() {
|
||||
doTest 'a.groovy', '''def x = '<selection>$a</selection>b/''', 'def x = "smth<caret>h"', 'def x = "smth\\$a<caret>h"'
|
||||
|
||||
}
|
||||
|
||||
public void testRestoreImports() {
|
||||
myFixture.addClass("package foo; public class Foo {}")
|
||||
|
||||
myFixture.configureByText 'a.groovy', '''import foo.*; <selection>Foo f</selection>'''
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', '<caret>'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult '''import foo.Foo
|
||||
doTest 'a.groovy', '''import foo.*; <selection>Foo f</selection>''', '<caret>', '''import foo.Foo
|
||||
|
||||
Foo f'''
|
||||
}
|
||||
|
||||
public void testPasteMultilineIntoMultilineGString() throws Exception {
|
||||
myFixture.configureByText 'a.txt', '<selection>a/b\nc/d</selection>'
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', 'def x = """smth<caret>"""'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult 'def x = """smtha/b\nc/d<caret>"""'
|
||||
doTest 'a.txt', '<selection>a/b\nc/d</selection>', 'def x = """smth<caret>"""', 'def x = """smtha/b\nc/d<caret>"""'
|
||||
}
|
||||
|
||||
public void testPasteMultilineIntoString() throws Exception {
|
||||
myFixture.configureByText 'a.txt', '<selection>a\nd</selection>'
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', "def x = 'smth<caret>'"
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult "def x = 'smtha\\n' +\n 'd<caret>'"
|
||||
doTest 'a.txt', '<selection>a\nd</selection>', "def x = 'smth<caret>'", "def x = 'smtha\\n' +\n 'd<caret>'"
|
||||
}
|
||||
|
||||
public void testPasteMultilineIntoGString() throws Exception {
|
||||
myFixture.configureByText 'a.txt', '<selection>a\nd</selection>'
|
||||
myFixture.performEditorAction IdeActions.ACTION_COPY
|
||||
myFixture.configureByText 'b.groovy', 'def x = "smth<caret>"'
|
||||
myFixture.performEditorAction IdeActions.ACTION_PASTE
|
||||
myFixture.checkResult 'def x = "smtha\\n" +\n "d<caret>"'
|
||||
doTest 'a.txt', '<selection>a\nd</selection>', 'def x = "smth<caret>"', 'def x = "smtha\\n" +\n "d<caret>"'
|
||||
}
|
||||
|
||||
public void testGStringEolReplace() throws Exception {
|
||||
doTest 'a.txt',
|
||||
'''<selection>first
|
||||
second
|
||||
</selection>''',
|
||||
'''def x = """
|
||||
<selection>foo
|
||||
</selection>"""''',
|
||||
'''def x = """
|
||||
first
|
||||
second
|
||||
<caret>"""'''
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -211,6 +211,22 @@ cl.parseClass('''$mcText''', 'MyClass.groovy').foo(2)
|
||||
eval 'a', '2'
|
||||
}
|
||||
}
|
||||
|
||||
void testAnonymousClassInScript() {
|
||||
myFixture.addFileToProject('Foo.groovy', '''\
|
||||
new Runnable() {
|
||||
void run() {
|
||||
print 'foo'
|
||||
}
|
||||
}.run()
|
||||
|
||||
''')
|
||||
addBreakpoint 'Foo.groovy', 2
|
||||
runDebugger 'Foo', {
|
||||
waitForBreakpoint()
|
||||
eval '1+1', '2'
|
||||
}
|
||||
}
|
||||
|
||||
private def addBreakpoint(String fileName, int line) {
|
||||
VirtualFile file = null
|
||||
|
||||
@@ -80,22 +80,26 @@ public final class ErrorAnalyzer {
|
||||
@Nullable final GuiEditor editor,
|
||||
@NotNull final IRootContainer rootContainer,
|
||||
@Nullable final ProgressIndicator progress) {
|
||||
if (module.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Validate class to bind
|
||||
final String classToBind = rootContainer.getClassToBind();
|
||||
final PsiClass psiClass;
|
||||
if(classToBind != null){
|
||||
if (classToBind != null) {
|
||||
psiClass = FormEditingUtil.findClassToBind(module, classToBind);
|
||||
if(psiClass == null){
|
||||
if (psiClass == null) {
|
||||
final QuickFix[] fixes = editor != null ? new QuickFix[]{new CreateClassToBindFix(editor, classToBind)} : QuickFix.EMPTY_ARRAY;
|
||||
final ErrorInfo errorInfo = new ErrorInfo(null, null, UIDesignerBundle.message("error.class.does.not.exist", classToBind),
|
||||
HighlightDisplayLevel.ERROR, fixes);
|
||||
rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, errorInfo);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, null);
|
||||
}
|
||||
}
|
||||
else{
|
||||
else {
|
||||
rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, null);
|
||||
psiClass = null;
|
||||
}
|
||||
@@ -116,13 +120,13 @@ public final class ErrorAnalyzer {
|
||||
final String binding = component.getBinding();
|
||||
|
||||
// a. Check that field exists and field is not static
|
||||
if(psiClass != null && binding != null) {
|
||||
if (psiClass != null && binding != null) {
|
||||
if (validateFieldInClass(component, binding, component.getComponentClassName(), psiClass, editor, module)) return true;
|
||||
}
|
||||
|
||||
// b. Check that binding is unique
|
||||
if (binding != null) {
|
||||
if(usedBindings.contains(binding)){
|
||||
if (usedBindings.contains(binding)) {
|
||||
// TODO[vova] implement
|
||||
component.putClientProperty(
|
||||
CLIENT_PROP_BINDING_ERROR,
|
||||
@@ -162,14 +166,14 @@ public final class ErrorAnalyzer {
|
||||
// Clear previous error (if any)
|
||||
component.putClientProperty(CLIENT_PROP_ERROR_ARRAY, null);
|
||||
|
||||
if(!(component instanceof IContainer)){
|
||||
if (!(component instanceof IContainer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final IContainer container = (IContainer)component;
|
||||
if(container instanceof IRootContainer){
|
||||
if (container instanceof IRootContainer) {
|
||||
final IRootContainer rootContainer = (IRootContainer)container;
|
||||
if(rootContainer.getComponentCount() > 1){
|
||||
if (rootContainer.getComponentCount() > 1) {
|
||||
// TODO[vova] implement
|
||||
putError(component, new ErrorInfo(
|
||||
component, null, UIDesignerBundle.message("error.multiple.toplevel.components"),
|
||||
@@ -178,13 +182,13 @@ public final class ErrorAnalyzer {
|
||||
));
|
||||
}
|
||||
}
|
||||
else if(container.isXY() && container.getComponentCount() > 0){
|
||||
else if (container.isXY() && container.getComponentCount() > 0) {
|
||||
// TODO[vova] implement
|
||||
putError(component, new ErrorInfo(
|
||||
component, null, UIDesignerBundle.message("error.panel.not.laid.out"),
|
||||
HighlightDisplayLevel.ERROR,
|
||||
QuickFix.EMPTY_ARRAY
|
||||
)
|
||||
component, null, UIDesignerBundle.message("error.panel.not.laid.out"),
|
||||
HighlightDisplayLevel.ERROR,
|
||||
QuickFix.EMPTY_ARRAY
|
||||
)
|
||||
);
|
||||
}
|
||||
return true;
|
||||
@@ -199,14 +203,14 @@ public final class ErrorAnalyzer {
|
||||
if (formPsiFile != null && rootContainer instanceof RadRootContainer) {
|
||||
final List<FormInspectionTool> formInspectionTools = new ArrayList<FormInspectionTool>();
|
||||
final FormInspectionTool[] registeredFormInspections = Extensions.getExtensions(FormInspectionTool.EP_NAME);
|
||||
for(FormInspectionTool formInspectionTool: registeredFormInspections) {
|
||||
for (FormInspectionTool formInspectionTool : registeredFormInspections) {
|
||||
if (formInspectionTool.isActive(formPsiFile) && !rootContainer.isInspectionSuppressed(formInspectionTool.getShortName(), null)) {
|
||||
formInspectionTools.add(formInspectionTool);
|
||||
}
|
||||
}
|
||||
|
||||
if (formInspectionTools.size() > 0 && editor != null) {
|
||||
for(FormInspectionTool tool: formInspectionTools) {
|
||||
for (FormInspectionTool tool : formInspectionTools) {
|
||||
tool.startCheckForm(rootContainer);
|
||||
}
|
||||
FormEditingUtil.iterate(
|
||||
@@ -215,7 +219,7 @@ public final class ErrorAnalyzer {
|
||||
public boolean visit(final RadComponent component) {
|
||||
if (progress != null && progress.isCanceled()) return false;
|
||||
|
||||
for(FormInspectionTool tool: formInspectionTools) {
|
||||
for (FormInspectionTool tool : formInspectionTools) {
|
||||
if (rootContainer.isInspectionSuppressed(tool.getShortName(), component.getId())) continue;
|
||||
ErrorInfo[] errorInfos = tool.checkComponent(editor, component);
|
||||
if (errorInfos != null) {
|
||||
@@ -231,7 +235,7 @@ public final class ErrorAnalyzer {
|
||||
}
|
||||
}
|
||||
);
|
||||
for(FormInspectionTool tool: formInspectionTools) {
|
||||
for (FormInspectionTool tool : formInspectionTools) {
|
||||
tool.doneCheckForm(rootContainer);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.uiDesigner.radComponents.RadComponent;
|
||||
import com.intellij.uiDesigner.radComponents.RadRootContainer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Anton Katilin
|
||||
@@ -39,9 +40,9 @@ final class ComponentPtrDescriptor extends NodeDescriptor<ComponentPtr> {
|
||||
myPtr=ptr;
|
||||
}
|
||||
|
||||
public boolean update(){
|
||||
public boolean update() {
|
||||
myPtr.validate();
|
||||
if(!myPtr.isValid()){
|
||||
if(!myPtr.isValid()) {
|
||||
myPtr=null;
|
||||
return true;
|
||||
}
|
||||
@@ -49,7 +50,10 @@ final class ComponentPtrDescriptor extends NodeDescriptor<ComponentPtr> {
|
||||
final String oldBinding = myBinding;
|
||||
final String oldTitle = myTitle;
|
||||
final RadComponent component = myPtr.getComponent();
|
||||
if(component instanceof RadRootContainer){
|
||||
if (component.getModule().isDisposed()) {
|
||||
return false;
|
||||
}
|
||||
if(component instanceof RadRootContainer) {
|
||||
myBinding = ((RadRootContainer)component).getClassToBind();
|
||||
}
|
||||
else{
|
||||
@@ -59,6 +63,7 @@ final class ComponentPtrDescriptor extends NodeDescriptor<ComponentPtr> {
|
||||
return !Comparing.equal(oldBinding,myBinding) || !Comparing.equal(oldTitle, myTitle);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RadComponent getComponent() {
|
||||
return myPtr != null ? myPtr.getComponent() : null;
|
||||
}
|
||||
|
||||
+10
-8
@@ -42,13 +42,8 @@ final class ComponentTreeStructure extends AbstractTreeStructure{
|
||||
private final GuiEditor myEditor;
|
||||
|
||||
public ComponentTreeStructure(@NotNull final GuiEditor editor){
|
||||
myRootElement=new Object() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "root of component tree structure " + ComponentTreeStructure.this.toString();
|
||||
}
|
||||
};
|
||||
myEditor=editor;
|
||||
myRootElement = new ComponentTreeStructureRoot();
|
||||
myEditor = editor;
|
||||
}
|
||||
|
||||
public Object getRootElement(){
|
||||
@@ -107,7 +102,7 @@ final class ComponentTreeStructure extends AbstractTreeStructure{
|
||||
}
|
||||
|
||||
public Object getParentElement(final Object element){
|
||||
if(element==myRootElement){
|
||||
if (element instanceof ComponentTreeStructureRoot) {
|
||||
return null;
|
||||
}
|
||||
else if (element instanceof LwInspectionSuppression[] || element instanceof RadButtonGroup[]) {
|
||||
@@ -180,4 +175,11 @@ final class ComponentTreeStructure extends AbstractTreeStructure{
|
||||
public boolean hasSomethingToCommit(){
|
||||
return false;
|
||||
}
|
||||
|
||||
private class ComponentTreeStructureRoot {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "root of component tree structure " + ComponentTreeStructure.this.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
<extensionPoint name="javaMainMethodProvider" interface="com.intellij.codeInsight.runner.JavaMainMethodProvider"/>
|
||||
|
||||
<extensionPoint name="debuggerClassFilterProvider" interface="com.intellij.ui.classFilter.DebuggerClassFilterProvider"/>
|
||||
<extensionPoint name="topLevelClassProvider" interface="com.intellij.debugger.engine.TopLevelParentClassProvider"/>
|
||||
|
||||
<extensionPoint name="debuggerEditorTextProvider" beanClass="com.intellij.lang.LanguageExtensionPoint" />
|
||||
|
||||
|
||||
@@ -615,7 +615,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag {
|
||||
|
||||
final int s = result.size();
|
||||
XmlTag[] tags = s > 0 ? ContainerUtil.toArray(result, new XmlTag[s]) : EMPTY;
|
||||
return Result.create(tags, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
return Result.create(tags, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, getContainingFile());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user