mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -37,10 +38,8 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -48,8 +47,16 @@ import java.util.Comparator;
|
||||
*/
|
||||
public class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
|
||||
@Nullable
|
||||
private Condition<Sdk> myFilter;
|
||||
|
||||
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel) {
|
||||
super(new JdkComboBoxModel(jdkModel));
|
||||
this(jdkModel, null);
|
||||
}
|
||||
|
||||
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel, @Nullable Condition<Sdk> filter) {
|
||||
super(new JdkComboBoxModel(jdkModel, filter));
|
||||
myFilter = filter;
|
||||
setRenderer(new ProjectJdkListRenderer(getRenderer()) {
|
||||
@Override
|
||||
public void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) {
|
||||
@@ -221,7 +228,10 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
model.removeAllElements();
|
||||
model.addElement(firstItem);
|
||||
final ProjectSdksModel projectJdksModel = ProjectStructureConfigurable.getInstance(project).getProjectJdksModel();
|
||||
final ArrayList<Sdk> projectJdks = new ArrayList<Sdk>(projectJdksModel.getProjectSdks().values());
|
||||
List<Sdk> projectJdks = new ArrayList<Sdk>(projectJdksModel.getProjectSdks().values());
|
||||
if (myFilter != null) {
|
||||
projectJdks = ContainerUtil.filter(projectJdks, myFilter);
|
||||
}
|
||||
Collections.sort(projectJdks, new Comparator<Sdk>() {
|
||||
public int compare(final Sdk o1, final Sdk o2) {
|
||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||
@@ -233,9 +243,12 @@ public class JdkComboBox extends ComboBoxWithWidePopup {
|
||||
}
|
||||
|
||||
private static class JdkComboBoxModel extends DefaultComboBoxModel {
|
||||
public JdkComboBoxModel(final ProjectSdksModel jdksModel) {
|
||||
super();
|
||||
final Sdk[] jdks = jdksModel.getSdks();
|
||||
public JdkComboBoxModel(final ProjectSdksModel jdksModel, final @Nullable Condition<Sdk> filter) {
|
||||
Sdk[] jdks = jdksModel.getSdks();
|
||||
if (filter != null) {
|
||||
final List<Sdk> filtered = ContainerUtil.filter(jdks, filter);
|
||||
jdks = filtered.toArray(new Sdk[filtered.size()]);
|
||||
}
|
||||
Arrays.sort(jdks, new Comparator<Sdk>() {
|
||||
public int compare(final Sdk s1, final Sdk s2) {
|
||||
return s1.getName().compareToIgnoreCase(s2.getName());
|
||||
|
||||
+3
-3
@@ -78,12 +78,12 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider());
|
||||
}
|
||||
|
||||
insertParentheses(context, delegate, psiClass, !inAnonymous && isAbstract);
|
||||
|
||||
if (item.getDelegate() instanceof JavaPsiClassReferenceElement) {
|
||||
DefaultInsertHandler.addImportForItem(context, delegate);
|
||||
PsiTypeLookupItem.addImportForItem(context, psiClass);
|
||||
}
|
||||
|
||||
insertParentheses(context, delegate, psiClass, !inAnonymous && isAbstract);
|
||||
|
||||
if (inAnonymous) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,18 +22,16 @@ import com.intellij.codeInsight.TailTypes;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DefaultInsertHandler extends TemplateInsertHandler implements Cloneable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.DefaultInsertHandler");
|
||||
|
||||
public static final DefaultInsertHandler NO_TAIL_HANDLER = new DefaultInsertHandler(){
|
||||
@Override
|
||||
@@ -54,8 +52,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone
|
||||
final Document document = editor.getDocument();
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
|
||||
final PsiFile file = context.getFile();
|
||||
|
||||
TailType tailType = getTailType(completionChar, item);
|
||||
|
||||
InsertHandlerState state = new InsertHandlerState(context.getSelectionEndOffset(), context.getSelectionEndOffset());
|
||||
@@ -73,8 +69,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone
|
||||
state.caretOffset = processTail(tailType, state.caretOffset, state.tailOffset, editor);
|
||||
editor.getSelectionModel().removeSelection();
|
||||
|
||||
addImportForItem(context, item);
|
||||
|
||||
if (tailType == TailType.DOT || context.getCompletionChar() == '.') {
|
||||
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null);
|
||||
}
|
||||
@@ -181,49 +175,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone
|
||||
JavaCompletionUtil.initOffsets(file, file.getProject(), offsetMap);
|
||||
}
|
||||
|
||||
public static void addImportForItem(InsertionContext context, LookupElement item) throws IncorrectOperationException {
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
|
||||
|
||||
int startOffset = context.getStartOffset();
|
||||
PsiFile file = context.getFile();
|
||||
Object o = item.getObject();
|
||||
if (o instanceof PsiClass){
|
||||
PsiClass aClass = (PsiClass)o;
|
||||
if (aClass.getQualifiedName() == null) return;
|
||||
final String lookupString = item.getLookupString();
|
||||
int length = lookupString.length();
|
||||
final int i = lookupString.indexOf('<');
|
||||
if (i >= 0) length = i;
|
||||
final int newOffset = addImportForClass(file, startOffset, startOffset + length, aClass);
|
||||
JavaCompletionUtil.shortenReference(file, newOffset);
|
||||
}
|
||||
else if (o instanceof PsiType){
|
||||
PsiType type = ((PsiType)o).getDeepComponentType();
|
||||
if (type instanceof PsiClassType) {
|
||||
PsiClass refClass = ((PsiClassType) type).resolve();
|
||||
if (refClass != null){
|
||||
int length = refClass.getName().length();
|
||||
addImportForClass(file, startOffset, startOffset + length, refClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (o instanceof PsiMethod){
|
||||
PsiMethod method = (PsiMethod)o;
|
||||
if (method.isConstructor()){
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
if (aClass != null){
|
||||
int length = method.getName().length();
|
||||
addImportForClass(file, startOffset, startOffset + length, aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int addImportForClass(PsiFile file, int startOffset, int endOffset, PsiClass aClass) throws IncorrectOperationException {
|
||||
return JavaCompletionUtil.insertClassReference(aClass, file, startOffset, endOffset);
|
||||
}
|
||||
|
||||
|
||||
public static class InsertHandlerState{
|
||||
int tailOffset;
|
||||
int caretOffset;
|
||||
|
||||
@@ -31,7 +31,7 @@ public class Java15CompletionData extends JavaCompletionData {
|
||||
//static keyword in static import
|
||||
{
|
||||
final CompletionVariant variant = new CompletionVariant(PsiImportList.class, new LeftNeighbour(new TextFilter (PsiKeyword.IMPORT)));
|
||||
variant.addCompletion(PsiKeyword.STATIC, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.STATIC, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
|
||||
registerVariant(variant);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public class Java15CompletionData extends JavaCompletionData {
|
||||
final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, position);
|
||||
variant.includeScopeClass(PsiClass.class);
|
||||
|
||||
variant.addCompletion(PsiKeyword.INTERFACE, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.INTERFACE, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
|
||||
registerVariant(variant);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public class Java15CompletionData extends JavaCompletionData {
|
||||
final CompletionVariant variant = new CompletionVariant(PsiJavaFile.class, CLASS_START);
|
||||
variant.includeScopeClass(PsiClass.class);
|
||||
|
||||
variant.addCompletion(PsiKeyword.ENUM, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.ENUM, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
registerVariant(variant);
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ public class Java15CompletionData extends JavaCompletionData {
|
||||
final CompletionVariant variant = new CompletionVariant(JavaMemberNameCompletionContributor.INSIDE_TYPE_PARAMS_PATTERN);
|
||||
variant.includeScopeClass(PsiVariable.class, true);
|
||||
variant.includeScopeClass(PsiExpressionStatement.class, true);
|
||||
variant.addCompletion(PsiKeyword.SUPER, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.SUPER, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
registerVariant(variant);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-13
@@ -19,8 +19,7 @@ import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.ExpectedTypesProvider;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.diagnostic.LogMessageEx;
|
||||
import com.intellij.diagnostic.errordialog.Attachment;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -90,8 +89,10 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
|
||||
if (fillTypeArgs) {
|
||||
context.setAddCompletionChar(false);
|
||||
}
|
||||
|
||||
if (shouldInsertParentheses(psiClass, position)) {
|
||||
|
||||
PsiTypeLookupItem.addImportForItem(context, psiClass);
|
||||
|
||||
if (shouldInsertParentheses(psiClass, file.findElementAt(context.getTailOffset() - 1))) {
|
||||
if (ConstructorInsertHandler.insertParentheses(context, item, psiClass, false)) {
|
||||
fillTypeArgs |= psiClass.hasTypeParameters() && PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_5);
|
||||
}
|
||||
@@ -101,15 +102,6 @@ class JavaClassNameInsertHandler implements InsertHandler<JavaPsiClassReferenceE
|
||||
AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null);
|
||||
}
|
||||
|
||||
LOG.assertTrue(context.getTailOffset() >= 0);
|
||||
String docText = context.getDocument().getText();
|
||||
DefaultInsertHandler.addImportForItem(context, item);
|
||||
if (context.getTailOffset() < 0) {
|
||||
LOG.error(LogMessageEx.createEvent("Tail offset degraded after insertion", "start=" + context.getStartOffset(),
|
||||
new Attachment(context.getFile().getViewProvider().getVirtualFile().getPath(), docText)));
|
||||
}
|
||||
|
||||
|
||||
if (annotation) {
|
||||
// Check if someone inserts annotation class that require @
|
||||
PsiElement elementAt = file.findElementAt(context.getStartOffset());
|
||||
|
||||
@@ -273,7 +273,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
// completion
|
||||
final CompletionVariant variant = new CompletionVariant(position);
|
||||
variant.includeScopeClass(PsiClass.class, true);
|
||||
variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
variant.excludeScopeClass(PsiAnonymousClass.class);
|
||||
variant.excludeScopeClass(PsiTypeParameter.class);
|
||||
|
||||
@@ -294,7 +294,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
// completion
|
||||
final CompletionVariant variant = new CompletionVariant(position);
|
||||
variant.includeScopeClass(PsiClass.class, true);
|
||||
variant.addCompletion(PsiKeyword.IMPLEMENTS, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.IMPLEMENTS, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
variant.excludeScopeClass(PsiAnonymousClass.class);
|
||||
|
||||
registerVariant(variant);
|
||||
@@ -306,7 +306,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
psiElement(PsiIdentifier.class).afterLeaf(
|
||||
psiElement().withText(string().oneOf(",", "<")).withParent(PsiTypeParameterList.class))));
|
||||
//variant.includeScopeClass(PsiClass.class, true);
|
||||
variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE);
|
||||
variant.addCompletion(PsiKeyword.EXTENDS, TailType.HUMBLE_SPACE_BEFORE_WORD);
|
||||
registerVariant(variant);
|
||||
}
|
||||
}
|
||||
@@ -414,7 +414,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
return TailType.SEMICOLON;
|
||||
}
|
||||
|
||||
return TailType.HUMBLE_SPACE;
|
||||
return TailType.HUMBLE_SPACE_BEFORE_WORD;
|
||||
}
|
||||
scope = scope.getParent();
|
||||
}
|
||||
@@ -456,7 +456,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
}
|
||||
if (statement != null && statement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) {
|
||||
if (!psiElement().withSuperParent(2, PsiSwitchStatement.class).accepts(statement)) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE));
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,13 +508,13 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
}
|
||||
|
||||
if (INSIDE_PARAMETER_LIST.accepts(position) && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) && !AFTER_DOT.accepts(position)) {
|
||||
result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE));
|
||||
result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
|
||||
if (CLASS_START.isAcceptable(position, position) &&
|
||||
PsiTreeUtil.getNonStrictParentOfType(position, PsiLiteralExpression.class, PsiComment.class) == null) {
|
||||
for (String s : ModifierChooser.getKeywords(position)) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE));
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,11 +589,11 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
isStatementPosition(position)) {
|
||||
for (String primitiveType : PRIMITIVE_TYPES) {
|
||||
LookupElement keyword = createKeyword(position, primitiveType);
|
||||
result.addElement(inCast ? keyword : new OverrideableSpace(keyword, TailType.HUMBLE_SPACE));
|
||||
result.addElement(inCast ? keyword : new OverrideableSpace(keyword, TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
if (declaration) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.HUMBLE_SPACE));
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,7 +606,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
|
||||
if (psiElement().insideSequence(true, psiElement(PsiLabeledStatement.class),
|
||||
or(psiElement(PsiFile.class), psiElement(PsiMethod.class),
|
||||
psiElement(PsiClassInitializer.class))).accepts(position)) {
|
||||
tailType = TailType.HUMBLE_SPACE;
|
||||
tailType = TailType.HUMBLE_SPACE_BEFORE_WORD;
|
||||
}
|
||||
else {
|
||||
tailType = TailType.SEMICOLON;
|
||||
|
||||
@@ -429,7 +429,7 @@ public class JavaCompletionUtil {
|
||||
|
||||
PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
|
||||
boolean checkInitialized = parameters.getInvocationCount() <= 1 && call != null && PsiKeyword.SUPER.equals(call.getMethodExpression().getText());
|
||||
|
||||
|
||||
final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, checkInitialized, filterStaticAfterInstance, nameCondition);
|
||||
javaReference.processVariants(processor);
|
||||
final Collection<CompletionElement> plainResults = processor.getResults();
|
||||
@@ -690,8 +690,8 @@ public class JavaCompletionUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int insertClassReference(@NotNull PsiClass psiClass, @NotNull PsiFile file, int offset) {
|
||||
return insertClassReference(psiClass, file, offset, offset);
|
||||
public static void insertClassReference(@NotNull PsiClass psiClass, @NotNull PsiFile file, int offset) {
|
||||
insertClassReference(psiClass, file, offset, offset);
|
||||
}
|
||||
|
||||
public static int insertClassReference(PsiClass psiClass, PsiFile file, int startOffset, int endOffset) {
|
||||
@@ -707,14 +707,14 @@ public class JavaCompletionUtil {
|
||||
final PsiElement resolved = reference.resolve();
|
||||
if (resolved instanceof PsiClass) {
|
||||
if (((PsiClass)resolved).getQualifiedName() == null || manager.areElementsEquivalent(psiClass, resolved)) {
|
||||
return startOffset;
|
||||
return endOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String name = psiClass.getName();
|
||||
if (name == null) {
|
||||
return startOffset;
|
||||
return endOffset;
|
||||
}
|
||||
|
||||
assert document != null;
|
||||
@@ -724,7 +724,7 @@ public class JavaCompletionUtil {
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
int newStartOffset = startOffset;
|
||||
int newEndOffset = endOffset;
|
||||
PsiElement element = file.findElementAt(startOffset);
|
||||
if (element instanceof PsiIdentifier) {
|
||||
PsiElement parent = element.getParent();
|
||||
@@ -739,7 +739,13 @@ public class JavaCompletionUtil {
|
||||
|
||||
newElement = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(newElement);
|
||||
if (newElement != null) {
|
||||
newStartOffset = newElement.getTextRange().getStartOffset();
|
||||
newEndOffset = newElement.getTextRange().getEndOffset();
|
||||
if (newElement instanceof PsiJavaCodeReferenceElement) {
|
||||
PsiReferenceParameterList parameterList = ((PsiJavaCodeReferenceElement)newElement).getParameterList();
|
||||
if (parameterList != null) {
|
||||
newEndOffset = parameterList.getTextRange().getStartOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!staticImport &&
|
||||
@@ -747,7 +753,7 @@ public class JavaCompletionUtil {
|
||||
!psiClass.getManager().areElementsEquivalent(psiClass, resolveReference((PsiReference)newElement))) {
|
||||
final String qName = psiClass.getQualifiedName();
|
||||
if (qName != null) {
|
||||
document.replaceString(newStartOffset, newElement.getTextRange().getEndOffset(), qName);
|
||||
document.replaceString(newElement.getTextRange().getStartOffset(), newEndOffset, qName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -758,7 +764,7 @@ public class JavaCompletionUtil {
|
||||
document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset());
|
||||
}
|
||||
|
||||
return newStartOffset;
|
||||
return newEndOffset;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -856,9 +862,7 @@ public class JavaCompletionUtil {
|
||||
//need to shorten references in type argument list
|
||||
public static void shortenReference(final PsiFile file, final int offset) throws IncorrectOperationException {
|
||||
final PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject());
|
||||
final Document document = manager.getDocument(file);
|
||||
assert document != null;
|
||||
manager.commitDocument(document);
|
||||
manager.commitDocument(manager.getDocument(file));
|
||||
final PsiReference ref = file.findReferenceAt(offset);
|
||||
if (ref instanceof PsiJavaCodeReferenceElement) {
|
||||
JavaCodeStyleManager.getInstance(file.getProject()).shortenClassReferences((PsiJavaCodeReferenceElement)ref);
|
||||
|
||||
+2
-2
@@ -264,7 +264,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
for (PsiClassType ref : method.getThrowsList().getReferencedTypes()) {
|
||||
final PsiClass exception = ref.resolve();
|
||||
if (exception != null && throwsSet.add(exception)) {
|
||||
result.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(exception), TailType.HUMBLE_SPACE));
|
||||
result.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(exception), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
|
||||
if (tryBlock == null) return;
|
||||
|
||||
for (final PsiClassType type : ExceptionUtil.getThrownExceptions(tryBlock.getStatements())) {
|
||||
result.addElement(TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(type, tryBlock).setInsertHandler(new DefaultInsertHandler()), TailType.HUMBLE_SPACE));
|
||||
result.addElement(TailTypeDecorator.withTail(PsiTypeLookupItem.createLookupItem(type, tryBlock).setInsertHandler(new DefaultInsertHandler()), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -73,14 +73,13 @@ public class PsiTypeLookupItem extends LookupItem {
|
||||
public void handleInsert(InsertionContext context) {
|
||||
PsiElement position = context.getFile().findElementAt(context.getStartOffset());
|
||||
assert position != null;
|
||||
if (getObject() instanceof PsiClass) {
|
||||
addImportForItem(context, (PsiClass)getObject());
|
||||
}
|
||||
context.getDocument().insertString(context.getTailOffset(), calcGenerics(position));
|
||||
DefaultInsertHandler.addImportForItem(context, this);
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
|
||||
JavaCompletionUtil.shortenReference(context.getFile(), context.getStartOffset());
|
||||
|
||||
int tail = context.getTailOffset();
|
||||
if (tail <= 0) {
|
||||
return;
|
||||
}
|
||||
String braces = StringUtil.repeat("[]", getBracketsCount());
|
||||
Editor editor = context.getEditor();
|
||||
if (!braces.isEmpty()) {
|
||||
@@ -227,4 +226,13 @@ public class PsiTypeLookupItem extends LookupItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addImportForItem(InsertionContext context, PsiClass aClass) {
|
||||
if (aClass.getQualifiedName() == null) return;
|
||||
PsiFile file = context.getFile();
|
||||
int newTail = JavaCompletionUtil.insertClassReference(aClass, file, context.getStartOffset(), context.getTailOffset());
|
||||
context.setTailOffset(newTail);
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
|
||||
JavaCompletionUtil.shortenReference(file, context.getStartOffset());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class AAA{}
|
||||
|
||||
class BBB extends AAA implements<caret> {
|
||||
class BBB extends AAA implements <caret> {
|
||||
}
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
class Foo {
|
||||
int ELEMENT_A = 1;
|
||||
int ELEMENT_B = 1;
|
||||
int ELEMENT_C = 1;
|
||||
int ELEMENT_D = 1;
|
||||
int ELEMENT_E = 1;
|
||||
int ELEMENT_F = 1;
|
||||
int ELEMENT_G = 1;
|
||||
int ELEMENT_H = 1;
|
||||
int ELEMENT_I = 1;
|
||||
|
||||
|
||||
{
|
||||
El<caret>
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -74,7 +74,7 @@ public class JavadocCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public void testSee0() throws Exception {
|
||||
configureByFile("See0.java");
|
||||
assertStringItems("foo", "clone", "equals", "finalize", "getClass", "hashCode", "notify", "notifyAll", "Object", "registerNatives", "toString", "wait", "wait", "wait");
|
||||
assertStringItems("foo", "clone", "equals", "getClass", "hashCode", "notify", "notifyAll", "Object", "toString", "wait", "wait", "wait", "finalize", "registerNatives");
|
||||
}
|
||||
|
||||
public void testSee1() throws Exception {
|
||||
|
||||
-10
@@ -233,16 +233,6 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
checkPreferredItems(0, "FooOCSomething", "FooObjectCollector");
|
||||
}
|
||||
|
||||
public void testPreselectMostRelevantInTheMiddle() {
|
||||
myFixture.addClass("package foo; public class Elaaaaaaaaaaaaaaaaaaaa {}");
|
||||
invokeCompletion(getTestName(false) + ".java");
|
||||
myFixture.completeBasic();
|
||||
LookupImpl lookup = getLookup();
|
||||
assertPreferredItems(lookup.getList().getSelectedIndex());
|
||||
assertEquals("Elaaaaaaaaaaaaaaaaaaaa", lookup.getItems().get(0).getLookupString());
|
||||
assertEquals("ELEMENT_A", lookup.getCurrentItem().getLookupString());
|
||||
}
|
||||
|
||||
public void testPreferSamePackageOverImported() {
|
||||
myFixture.addClass("package bar; public class Bar1 {}");
|
||||
myFixture.addClass("package bar; public class Bar2 {}");
|
||||
|
||||
+1
-1
@@ -474,7 +474,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public void testVoidExpectedType() throws Throwable {
|
||||
configureByTestName();
|
||||
assertStringItems("notify", "notifyAll", "wait", "wait", "wait", "equals", "getClass", "hashCode", "toString");
|
||||
assertStringItems("notify", "notifyAll", "wait", "wait", "wait", "getClass", "equals", "hashCode", "toString");
|
||||
type('e');
|
||||
assertEquals("equals", assertOneElement(getLookup().getItems()).getLookupString());
|
||||
select();
|
||||
|
||||
@@ -38,6 +38,10 @@ public class Paths {
|
||||
}
|
||||
|
||||
public static URI toURI(String localPath) {
|
||||
return toURI(localPath, true);
|
||||
}
|
||||
|
||||
private static URI toURI(String localPath, boolean convertSpaces) {
|
||||
try {
|
||||
String p = FileUtil.toSystemIndependentName(localPath);
|
||||
if (!p.startsWith("/")) {
|
||||
@@ -46,7 +50,7 @@ public class Paths {
|
||||
if (p.startsWith("//")) {
|
||||
p = "//" + p;
|
||||
}
|
||||
return new URI("file", null, p.replaceAll(" ", "%20"), null);
|
||||
return new URI("file", null, convertSpaces? p.replaceAll(" ", "%20") : p, null);
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new Error(e);
|
||||
@@ -54,6 +58,6 @@ public class Paths {
|
||||
}
|
||||
|
||||
public static File convertToFile(final URI uri) {
|
||||
return new File(toURI(uri.getPath()));
|
||||
return new File(toURI(uri.getPath(), false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
|
||||
}
|
||||
|
||||
private File findOutputDir(File src) {
|
||||
File file = src.getParentFile();
|
||||
File file = FileUtil.getParentFile(src);
|
||||
while (file != null) {
|
||||
for (Map.Entry<File, Set<File>> entry : myOutputsMap.entrySet()) {
|
||||
if (entry.getValue().contains(file)) {
|
||||
|
||||
@@ -96,14 +96,15 @@ public abstract class TailType {
|
||||
*/
|
||||
public static final TailType INSERT_SPACE = new CharTailType(' ', false);
|
||||
/**
|
||||
* insert a space unless there's one at the caret position already
|
||||
* insert a space unless there's one at the caret position already, followed by a sowrd
|
||||
*/
|
||||
public static final TailType HUMBLE_SPACE = new CharTailType(' ', false) {
|
||||
public static final TailType HUMBLE_SPACE_BEFORE_WORD = new CharTailType(' ', false) {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull InsertionContext context) {
|
||||
CharSequence text = context.getDocument().getCharsSequence();
|
||||
if (text.length() > context.getTailOffset() && text.charAt(context.getTailOffset()) == ' ') {
|
||||
int tail = context.getTailOffset();
|
||||
if (text.length() > tail + 1 && text.charAt(tail) == ' ' && Character.isLetter(text.charAt(tail + 1))) {
|
||||
return false;
|
||||
}
|
||||
return super.isApplicable(context);
|
||||
@@ -111,7 +112,7 @@ public abstract class TailType {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HUMBLE_SPACE";
|
||||
return "HUMBLE_SPACE_BEFORE_WORD";
|
||||
}
|
||||
};
|
||||
public static final TailType DOT = new CharTailType('.');
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ public class CompletionLookupArranger extends LookupArranger {
|
||||
CompletionLocation myLocation = new CompletionLocation(indicator.getParameters());
|
||||
final StatisticsInfo main = StatisticsManager.serialize(CompletionService.STATISTICS_KEY, item, myLocation);
|
||||
final List<LookupElement> items = lookupImpl.getItems();
|
||||
final int count = Math.min(lookupImpl.getPreferredItemsCount(), lookupImpl.getList().getSelectedIndex());
|
||||
final int count = Math.min(3, lookupImpl.getList().getSelectedIndex());
|
||||
|
||||
final List<StatisticsInfo> ignored = new ArrayList<StatisticsInfo>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
@@ -149,12 +149,6 @@ public class LookupCellRenderer implements ListCellRenderer {
|
||||
}
|
||||
|
||||
private Color getItemBackground(JList list, int index, boolean isSelected) {
|
||||
final int preferredCount = myLookup.getPreferredItemsCount();
|
||||
final boolean isPreferred = index <= preferredCount - 1 && preferredCount < list.getModel().getSize() - 1 && LookupImpl.limitRelevance();
|
||||
|
||||
if (isPreferred) {
|
||||
return isSelected ? SELECTED_BACKGROUND_COLOR : PREFERRED_BACKGROUND_COLOR;
|
||||
}
|
||||
return isSelected ? SELECTED_BACKGROUND_COLOR : BACKGROUND_COLOR;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -100,7 +99,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
private final Project myProject;
|
||||
private final Editor myEditor;
|
||||
|
||||
private int myPreferredItemsCount;
|
||||
private String myInitialPrefix;
|
||||
|
||||
private boolean myStableStart;
|
||||
@@ -258,10 +256,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
}
|
||||
}
|
||||
|
||||
public int getPreferredItemsCount() {
|
||||
return myPreferredItemsCount;
|
||||
}
|
||||
|
||||
public void markSelectionTouched() {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
@@ -428,7 +422,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
}
|
||||
}
|
||||
|
||||
myPreferredItemsCount = model.size();
|
||||
myFrozenItems.clear();
|
||||
if (myShown) {
|
||||
myFrozenItems.addAll(model);
|
||||
@@ -443,8 +436,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
}
|
||||
});
|
||||
model.addAll(elements);
|
||||
} else if (limitRelevance()) {
|
||||
model.addAll(addRemainingItemsLexicographically(model, items));
|
||||
} else {
|
||||
for (List<LookupElement> group : snapshot.second) {
|
||||
for (LookupElement element : group) {
|
||||
@@ -579,16 +570,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
return p;
|
||||
}
|
||||
|
||||
private static List<LookupElement> addRemainingItemsLexicographically(Set<LookupElement> firstItems, Collection<LookupElement> allItems) {
|
||||
List<LookupElement> model = new ArrayList<LookupElement>();
|
||||
for (LookupElement item : allItems) {
|
||||
if (!firstItems.contains(item)) {
|
||||
model.add(item);
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
private void addMostRelevantItems(final Set<LookupElement> model, final Iterable<List<LookupElement>> sortedItems) {
|
||||
if (model.size() > MAX_PREFERRED_COUNT) return;
|
||||
|
||||
@@ -605,10 +586,6 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean limitRelevance() {
|
||||
return ApplicationManager.getApplication().isUnitTestMode() || Registry.is("limited.relevance.sorting.in.completion");
|
||||
}
|
||||
|
||||
public boolean isFrozen(@NotNull LookupElement element) {
|
||||
return myFrozenItems.contains(element);
|
||||
}
|
||||
|
||||
+25
@@ -71,6 +71,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
Collections.sort(matchingTemplates, TemplateListPanel.TEMPLATE_COMPARATOR);
|
||||
showTemplatesLookup(project, editor, prefix, matchingTemplates);
|
||||
}
|
||||
|
||||
@@ -78,6 +79,30 @@ public class ListTemplatesHandler implements CodeInsightActionHandler {
|
||||
@NotNull String prefix, List<TemplateImpl> matchingTemplates) {
|
||||
|
||||
final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, LookupElement.EMPTY_ARRAY, prefix, LookupArranger.DEFAULT);
|
||||
lookup.setArranger(new LookupArranger() {
|
||||
/*
|
||||
@Override
|
||||
public Comparator<LookupElement> getItemComparator() {
|
||||
return new Comparator<LookupElement>() {
|
||||
@Override
|
||||
public int compare(LookupElement o1, LookupElement o2) {
|
||||
return o1.getLookupString().compareToIgnoreCase(o2.getLookupString());
|
||||
}
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Classifier<LookupElement> createRelevanceClassifier() {
|
||||
return new ComparingClassifier<LookupElement>(ClassifierFactory.<LookupElement>listClassifier(), "preferPrefix") {
|
||||
@NotNull
|
||||
@Override
|
||||
public Comparable getWeight(LookupElement element) {
|
||||
return !element.getLookupString().startsWith(lookup.itemPattern(element));
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
for (TemplateImpl template : matchingTemplates) {
|
||||
lookup.addItem(createTemplateElement(template), new PlainPrefixMatcher(prefix));
|
||||
}
|
||||
|
||||
+10
-9
@@ -63,6 +63,11 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
private static final String TEMPLATE_SETTINGS = "TemplateSettings";
|
||||
private static final TemplateImpl MOCK_TEMPLATE = new TemplateImpl("mockTemplate-xxx", "mockTemplateGroup-yyy");
|
||||
public static final String ABBREVIATION = "<abbreviation>";
|
||||
public static final Comparator<TemplateImpl> TEMPLATE_COMPARATOR = new Comparator<TemplateImpl>() {
|
||||
public int compare(final TemplateImpl o1, final TemplateImpl o2) {
|
||||
return o1.getKey().compareToIgnoreCase(o2.getKey());
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
MOCK_TEMPLATE.setString("");
|
||||
@@ -485,7 +490,7 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
|
||||
TreePath[] paths = myTree.getSelectionPaths();
|
||||
if (paths == null) return;
|
||||
|
||||
|
||||
for (TreePath path : paths) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
|
||||
Object o = node.getUserObject();
|
||||
@@ -652,7 +657,7 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
}
|
||||
})
|
||||
.install();
|
||||
|
||||
|
||||
if (myTemplateGroups.size() > 0) {
|
||||
myTree.setSelectionInterval(0, 0);
|
||||
}
|
||||
@@ -770,10 +775,10 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
|
||||
if (enabled) {
|
||||
Set<String> oldGroups = getAllGroups(templates);
|
||||
|
||||
|
||||
removeAll();
|
||||
SchemesManager<TemplateGroup, TemplateGroup> schemesManager = TemplateSettings.getInstance().getSchemesManager();
|
||||
|
||||
|
||||
for (TemplateGroup group : getTemplateGroups()) {
|
||||
final String newGroupName = group.getName();
|
||||
if (!oldGroups.contains(newGroupName) && !schemesManager.isShared(group)) {
|
||||
@@ -976,11 +981,7 @@ public class TemplateListPanel extends JPanel implements Disposable {
|
||||
|
||||
private void addTemplateNodes(TemplateGroup group, CheckedTreeNode groupNode) {
|
||||
List<TemplateImpl> templates = new ArrayList<TemplateImpl>(group.getElements());
|
||||
Collections.sort(templates, new Comparator<TemplateImpl>() {
|
||||
public int compare(final TemplateImpl o1, final TemplateImpl o2) {
|
||||
return o1.getKey().compareToIgnoreCase(o2.getKey());
|
||||
}
|
||||
});
|
||||
Collections.sort(templates, TEMPLATE_COMPARATOR);
|
||||
for (final TemplateImpl template : templates) {
|
||||
myTemplateOptions.put(getKey(template), template.createOptions());
|
||||
myTemplateContext.put(getKey(template), template.createContext());
|
||||
|
||||
@@ -26,7 +26,9 @@ import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -50,23 +52,19 @@ public class DumpLookupElementWeights extends AnAction implements DumbAware {
|
||||
}
|
||||
|
||||
public static void dumpLookupElementWeights(final LookupImpl lookup) {
|
||||
final LinkedHashMap<LookupElement,StringBuilder> strings = lookup.getRelevanceStrings();
|
||||
|
||||
final List<LookupElement> items = lookup.getItems();
|
||||
final int count = lookup.getPreferredItemsCount();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
LookupElement item = items.get(i);
|
||||
String weight = strings.get(item).toString();
|
||||
final String s = item.getLookupString() + (lookup.isFrozen(item) ? "\t_first_\t" : "\t") + weight;
|
||||
System.out.println(s);
|
||||
LOG.info(s);
|
||||
if (i == count - 1) {
|
||||
final String separator = "------------";
|
||||
System.out.println(separator);
|
||||
LOG.info(separator);
|
||||
}
|
||||
}
|
||||
String sb = StringUtil.join(getLookupElementWeights(lookup), "\n");
|
||||
System.out.println(sb);
|
||||
LOG.info(sb);
|
||||
}
|
||||
|
||||
public static List<String> getLookupElementWeights(LookupImpl lookup) {
|
||||
final LinkedHashMap<LookupElement,StringBuilder> strings = lookup.getRelevanceStrings();
|
||||
List<String> sb = new ArrayList<String>();
|
||||
for (LookupElement item : lookup.getItems()) {
|
||||
String weight = strings.get(item).toString();
|
||||
final String s = item.getLookupString() + (lookup.isFrozen(item) ? "\t_first_\t" : "\t") + weight;
|
||||
sb.add(s);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
@@ -215,6 +215,10 @@ public class ParametersList implements Cloneable {
|
||||
public void replaceOrPrepend(final @NonNls String parameter, final @NonNls String replacement) {
|
||||
replaceOrAdd(parameter, replacement, 0);
|
||||
}
|
||||
|
||||
public void set(int ind, final @NonNls String value) {
|
||||
myParameters.set(ind, value);
|
||||
}
|
||||
|
||||
public void add(@NonNls final String name, @NonNls final String value) {
|
||||
add(name);
|
||||
|
||||
@@ -24,9 +24,12 @@ import com.intellij.notification.impl.NotificationsManagerImpl;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.actions.ScrollToTheEndToolbarAction;
|
||||
import com.intellij.openapi.editor.actions.ToggleUseSoftWrapsToolbarAction;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
@@ -43,6 +46,8 @@ import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentFactory;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -52,8 +57,9 @@ import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -116,67 +122,134 @@ public class EventLog implements Notifications {
|
||||
}
|
||||
|
||||
public static LogEntry formatForLog(@NotNull final Notification notification) {
|
||||
DocumentImpl document = new DocumentImpl(true);
|
||||
AtomicBoolean showMore = new AtomicBoolean(false);
|
||||
Map<RangeMarker, HyperlinkInfo> links = new LinkedHashMap<RangeMarker, HyperlinkInfo>();
|
||||
List<RangeMarker> lineSeparators = new ArrayList<RangeMarker>();
|
||||
|
||||
boolean hasHtml = parseHtmlContent(notification, document, showMore, links, lineSeparators);
|
||||
removeJavaNewLines(document, lineSeparators, hasHtml);
|
||||
insertNewLineSubstitutors(document, showMore, lineSeparators);
|
||||
|
||||
String status = document.getText();
|
||||
|
||||
ArrayList<Pair<TextRange, HyperlinkInfo>> list = new ArrayList<Pair<TextRange, HyperlinkInfo>>();
|
||||
for (RangeMarker marker : links.keySet()) {
|
||||
if (!marker.isValid()) {
|
||||
showMore.set(true);
|
||||
continue;
|
||||
}
|
||||
list.add(Pair.create(new TextRange(marker.getStartOffset(), marker.getEndOffset()), links.get(marker)));
|
||||
}
|
||||
|
||||
if (showMore.get()) {
|
||||
String sb = "show balloon";
|
||||
appendText(document, " (" + sb + ")");
|
||||
list.add(new Pair<TextRange, HyperlinkInfo>(TextRange.from(document.getTextLength() - 1 - sb.length(), sb.length()),
|
||||
new ShowBalloon(notification)));
|
||||
}
|
||||
|
||||
return new LogEntry(document.getText(), status, list);
|
||||
}
|
||||
|
||||
private static boolean parseHtmlContent(Notification notification,
|
||||
Document document,
|
||||
AtomicBoolean showMore,
|
||||
Map<RangeMarker, HyperlinkInfo> links, List<RangeMarker> lineSeparators) {
|
||||
String content = notification.getContent();
|
||||
String mainText = notification.getTitle();
|
||||
boolean showMore = false;
|
||||
if (StringUtil.isNotEmpty(content)) {
|
||||
if (content.startsWith("<p>")) {
|
||||
content = content.substring("<p>".length());
|
||||
}
|
||||
|
||||
if (content.startsWith("<") && !content.startsWith("<a ")) {
|
||||
showMore = true;
|
||||
}
|
||||
if (StringUtil.isNotEmpty(mainText)) {
|
||||
mainText += ": ";
|
||||
}
|
||||
mainText += content;
|
||||
String title = notification.getTitle();
|
||||
if (StringUtil.isNotEmpty(title)) {
|
||||
content = title + (StringUtil.isNotEmpty(content) ? ": " + content : "");
|
||||
}
|
||||
|
||||
mainText = StringUtil.replace(mainText, " ", " ");
|
||||
int nlIndex = eolIndex(mainText);
|
||||
if (nlIndex >= 0) {
|
||||
mainText = mainText.substring(0, nlIndex);
|
||||
showMore = true;
|
||||
}
|
||||
|
||||
List<Pair<TextRange, HyperlinkInfo>> links = new ArrayList<Pair<TextRange, HyperlinkInfo>>();
|
||||
|
||||
String message = "";
|
||||
content = StringUtil.replace(StringUtil.convertLineSeparators(content), " ", " ");
|
||||
boolean hasHtml = false;
|
||||
while (true) {
|
||||
Matcher tagMatcher = TAG_PATTERN.matcher(mainText);
|
||||
Matcher tagMatcher = TAG_PATTERN.matcher(content);
|
||||
if (!tagMatcher.find()) {
|
||||
message += mainText;
|
||||
appendText(document, content);
|
||||
break;
|
||||
}
|
||||
message += mainText.substring(0, tagMatcher.start());
|
||||
Matcher aMatcher = A_PATTERN.matcher(tagMatcher.group());
|
||||
|
||||
String tagStart = tagMatcher.group();
|
||||
appendText(document, content.substring(0, tagMatcher.start()));
|
||||
Matcher aMatcher = A_PATTERN.matcher(tagStart);
|
||||
if (aMatcher.matches()) {
|
||||
final String href = aMatcher.group(2);
|
||||
int linkEnd = mainText.indexOf(A_CLOSING, tagMatcher.end());
|
||||
int linkEnd = content.indexOf(A_CLOSING, tagMatcher.end());
|
||||
if (linkEnd > 0) {
|
||||
String linkText = mainText.substring(tagMatcher.end(), linkEnd).replaceAll(TAG_PATTERN.pattern(), "");
|
||||
String linkText = content.substring(tagMatcher.end(), linkEnd).replaceAll(TAG_PATTERN.pattern(), "");
|
||||
appendText(document, linkText);
|
||||
links.put(document.createRangeMarker(new TextRange(document.getTextLength() - linkText.length(), document.getTextLength())),
|
||||
new NotificationHyperlinkInfo(notification, href));
|
||||
content = content.substring(linkEnd + A_CLOSING.length());
|
||||
}
|
||||
}
|
||||
else {
|
||||
hasHtml = true;
|
||||
if ("<br>".equals(tagStart) ||
|
||||
"</br>".equals(tagStart) ||
|
||||
"</p>".equals(tagStart) ||
|
||||
"<p>".equals(tagStart) ||
|
||||
"<p/>".equals(tagStart)) {
|
||||
lineSeparators.add(document.createRangeMarker(TextRange.from(document.getTextLength(), 0)));
|
||||
}
|
||||
else if (!"<html>".equals(tagStart) && !"</html>".equals(tagStart) && !"<body>".equals(tagStart) && !"</body>".equals(tagStart)) {
|
||||
showMore.set(true);
|
||||
}
|
||||
content = content.substring(tagMatcher.end());
|
||||
}
|
||||
}
|
||||
return hasHtml;
|
||||
}
|
||||
|
||||
links.add(new Pair<TextRange, HyperlinkInfo>(TextRange.from(message.length(), linkText.length()), new NotificationHyperlinkInfo(notification, href)));
|
||||
|
||||
message += linkText;
|
||||
mainText = mainText.substring(linkEnd + A_CLOSING.length());
|
||||
private static void insertNewLineSubstitutors(Document document, AtomicBoolean showMore, List<RangeMarker> lineSeparators) {
|
||||
for (int j = lineSeparators.size() - 1; j >= 0; j--) {
|
||||
RangeMarker marker = lineSeparators.get(j);
|
||||
if (!marker.isValid()) {
|
||||
showMore.set(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
int offset = marker.getStartOffset();
|
||||
if (offset == 0 || offset == document.getTextLength()) {
|
||||
continue;
|
||||
}
|
||||
boolean spaceBefore = offset > 0 && Character.isWhitespace(document.getCharsSequence().charAt(offset - 1));
|
||||
if (offset < document.getTextLength()) {
|
||||
boolean spaceAfter = Character.isWhitespace(document.getCharsSequence().charAt(offset));
|
||||
int next = CharArrayUtil.shiftForward(document.getCharsSequence(), offset, " \t");
|
||||
if (next < document.getTextLength() && Character.isUpperCase(document.getCharsSequence().charAt(next))) {
|
||||
document.insertString(offset, (spaceBefore ? "" : " ") + "//" + (spaceAfter ? "" : " "));
|
||||
continue;
|
||||
}
|
||||
if (spaceAfter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mainText = mainText.substring(tagMatcher.end());
|
||||
if (spaceBefore) {
|
||||
continue;
|
||||
}
|
||||
|
||||
document.insertString(offset, " ");
|
||||
}
|
||||
}
|
||||
|
||||
message = StringUtil.unescapeXml(StringUtil.convertLineSeparators(message));
|
||||
|
||||
String status = message;
|
||||
|
||||
if (showMore) {
|
||||
message += " more ";
|
||||
links.add(new Pair<TextRange, HyperlinkInfo>(TextRange.from(message.length() - 5, 4), new ShowBalloon(notification)));
|
||||
private static void removeJavaNewLines(Document document, List<RangeMarker> lineSeparators, boolean hasHtml) {
|
||||
String text = document.getText();
|
||||
int i = -1;
|
||||
while (true) {
|
||||
i = text.indexOf('\n', i + 1);
|
||||
if (i < 0) break;
|
||||
document.deleteString(i, i + 1);
|
||||
if (!hasHtml) {
|
||||
lineSeparators.add(document.createRangeMarker(TextRange.from(i, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new LogEntry(message, status, links);
|
||||
private static void appendText(Document document, String text) {
|
||||
document.insertString(document.getTextLength(), StringUtil.unescapeXml(text));
|
||||
}
|
||||
|
||||
public static class LogEntry {
|
||||
@@ -191,22 +264,6 @@ public class EventLog implements Notifications {
|
||||
}
|
||||
}
|
||||
|
||||
private static int eolIndex(String mainText) {
|
||||
TreeSet<Integer> indices = new TreeSet<Integer>();
|
||||
indices.add(mainText.indexOf("<br>", 1));
|
||||
indices.add(mainText.indexOf("<br/>", 1));
|
||||
indices.add(mainText.indexOf("<p/>", 1));
|
||||
indices.add(mainText.indexOf("<p>", 1));
|
||||
indices.add(mainText.indexOf("\n"));
|
||||
indices.remove(-1);
|
||||
return indices.isEmpty() ? -1 : indices.iterator().next();
|
||||
}
|
||||
|
||||
public static boolean isEventLogVisible(Project project) {
|
||||
final ToolWindow window = getEventLog(project);
|
||||
return window != null && window.isVisible();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ToolWindow getEventLog(Project project) {
|
||||
return project == null ? null : ToolWindowManager.getInstance(project).getToolWindow(LOG_TOOL_WINDOW_ID);
|
||||
|
||||
@@ -171,8 +171,6 @@ documentation.component.editor.font=false
|
||||
ide.mac.useNativeClipboard=false
|
||||
|
||||
show.all.classes.on.first.completion=false
|
||||
limited.relevance.sorting.in.completion=false
|
||||
limited.relevance.sorting.in.completion.description=Whether only 5 most relevant items are shown at the top of the completion list, or it's sorted by relevance completely
|
||||
ide.enable.toolwindow.stack=false
|
||||
|
||||
change.signature.awesome.mode=true
|
||||
|
||||
@@ -15,16 +15,52 @@
|
||||
*/
|
||||
package com.intellij.notification;
|
||||
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.testFramework.LightPlatformTestCase
|
||||
import com.intellij.testFramework.PlatformTestCase
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class EventLogTest extends UsefulTestCase {
|
||||
class EventLogTest extends LightPlatformTestCase {
|
||||
|
||||
EventLogTest() {
|
||||
PlatformTestCase.initPlatformLangPrefix()
|
||||
}
|
||||
|
||||
public void testNbsp() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "Hello world", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: Hello world'
|
||||
}
|
||||
|
||||
public void testParseMultilineText() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "<html><body> " +
|
||||
"<font size=\"3\">first line<br>" +
|
||||
"second line<br>" +
|
||||
"third<br>" +
|
||||
"<a href=\"create\">Action</a><br>" +
|
||||
"</body></html>", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: first line second line third // Action (show balloon)'
|
||||
// 0 40 48 60
|
||||
assert entry.links.collect { it.first } == [new TextRange(40, 46), new TextRange(48, 60)]
|
||||
|
||||
}
|
||||
|
||||
public void testInParagraph() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "<p>message</p>", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: message'
|
||||
}
|
||||
|
||||
public void testJavaSeparators() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "fst\nsnd", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: fst snd'
|
||||
}
|
||||
|
||||
public void testLinkInTitle() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", '<a href="a">link</a>', "content", NotificationType.ERROR))
|
||||
assert entry.message == 'link: content'
|
||||
assert entry.links.collect { it.first } == [new TextRange(0, 4)]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-17
@@ -49,6 +49,7 @@ import com.intellij.ide.startup.StartupManagerEx;
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.structureView.newStructureView.StructureViewComponent;
|
||||
import com.intellij.internal.DumpLookupElementWeights;
|
||||
import com.intellij.lang.LanguageStructureViewBuilder;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
@@ -1747,25 +1748,12 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
final LookupImpl lookup = getLookup();
|
||||
assertNotNull(lookup);
|
||||
|
||||
final LinkedHashMap<LookupElement,StringBuilder> relevanceStrings = lookup.getRelevanceStrings();
|
||||
|
||||
final JList list = lookup.getList();
|
||||
final List<LookupElement> model = lookup.getItems();
|
||||
final List<String> actual = new ArrayList<String>();
|
||||
final int count = lookup.getPreferredItemsCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
actual.add(model.get(i).getLookupString());
|
||||
}
|
||||
List<String> strings = getLookupElementStrings();
|
||||
assert strings != null;
|
||||
final List<String> actual = strings.subList(0, Math.min(expected.length, strings.size()));
|
||||
if (!actual.equals(Arrays.asList(expected))) {
|
||||
final List<String> strings = new ArrayList<String>();
|
||||
for (int i = 0; i < model.size(); i++) {
|
||||
final LookupElement item = model.get(i);
|
||||
strings.add(item.getLookupString() + " " + relevanceStrings.get(item));
|
||||
if (i == count - 1) {
|
||||
strings.add("---");
|
||||
}
|
||||
}
|
||||
assertOrderedEquals(strings, expected);
|
||||
assertOrderedEquals(DumpLookupElementWeights.getLookupElementWeights(lookup), expected);
|
||||
}
|
||||
assertEquals(selected, list.getSelectedIndex());
|
||||
}
|
||||
|
||||
+31
-15
@@ -44,12 +44,10 @@ import com.intellij.openapi.vcs.changes.ui.RollbackProgressModifier;
|
||||
import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class RollbackAction extends AnAction implements DumbAware {
|
||||
public void update(AnActionEvent e) {
|
||||
@@ -106,15 +104,25 @@ public class RollbackAction extends AnAction implements DumbAware {
|
||||
new RollbackDeletionAction().actionPerformed(e);
|
||||
}
|
||||
|
||||
List<VirtualFile> modifiedWithoutEditing = getModifiedWithoutEditing(e);
|
||||
LinkedHashSet<VirtualFile> modifiedWithoutEditing = getModifiedWithoutEditing(e, project);
|
||||
if (modifiedWithoutEditing != null && !modifiedWithoutEditing.isEmpty()) {
|
||||
hasChanges = true;
|
||||
rollbackModifiedWithoutEditing(project, modifiedWithoutEditing);
|
||||
}
|
||||
|
||||
Change[] changes = getChanges(project, e);
|
||||
if (changes != null && (changes.length > 0 || !hasChanges)) {
|
||||
RollbackChangesDialog.rollbackChanges(project, Arrays.asList(changes));
|
||||
List<Change> changes = getChanges(project, e);
|
||||
if (changes != null) {
|
||||
if (modifiedWithoutEditing != null) {
|
||||
for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext(); ) {
|
||||
Change next = iterator.next();
|
||||
if (modifiedWithoutEditing.contains(next.getVirtualFile())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!changes.isEmpty() || !hasChanges) {
|
||||
RollbackChangesDialog.rollbackChanges(project, changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +163,9 @@ public class RollbackAction extends AnAction implements DumbAware {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Change[] getChanges(final Project project, final AnActionEvent e) {
|
||||
private static List<Change> getChanges(final Project project, final AnActionEvent e) {
|
||||
final ChangesCheckHelper helper = new ChangesCheckHelper(project, e);
|
||||
if (helper.isChangesSet()) return helper.getChanges();
|
||||
if (helper.isChangesSet()) return CollectionFactory.arrayList(helper.getChanges());
|
||||
|
||||
final VirtualFile[] virtualFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
|
||||
if (virtualFiles != null && virtualFiles.length > 0) {
|
||||
@@ -165,23 +173,31 @@ public class RollbackAction extends AnAction implements DumbAware {
|
||||
for(VirtualFile file: virtualFiles) {
|
||||
result.addAll(ChangeListManager.getInstance(project).getChangesIn(file));
|
||||
}
|
||||
return result.toArray(new Change[result.size()]);
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<VirtualFile> getModifiedWithoutEditing(final AnActionEvent e) {
|
||||
private static LinkedHashSet<VirtualFile> getModifiedWithoutEditing(final AnActionEvent e, Project project) {
|
||||
final List<VirtualFile> modifiedWithoutEditing = e.getData(VcsDataKeys.MODIFIED_WITHOUT_EDITING_DATA_KEY);
|
||||
if (modifiedWithoutEditing != null && modifiedWithoutEditing.size() > 0) {
|
||||
return modifiedWithoutEditing;
|
||||
return new LinkedHashSet<VirtualFile>(modifiedWithoutEditing);
|
||||
}
|
||||
|
||||
final VirtualFile[] virtualFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
|
||||
if (virtualFiles != null && virtualFiles.length > 0) {
|
||||
LinkedHashSet<VirtualFile> result = new LinkedHashSet<VirtualFile>(Arrays.asList(virtualFiles));
|
||||
result.retainAll(ChangeListManager.getInstance(project).getModifiedWithoutEditing());
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void rollbackModifiedWithoutEditing(final Project project, final List<VirtualFile> modifiedWithoutEditing) {
|
||||
private static void rollbackModifiedWithoutEditing(final Project project, final LinkedHashSet<VirtualFile> modifiedWithoutEditing) {
|
||||
String message = (modifiedWithoutEditing.size() == 1)
|
||||
? VcsBundle.message("rollback.modified.without.editing.confirm.single", modifiedWithoutEditing.get(0).getPresentableUrl())
|
||||
? VcsBundle.message("rollback.modified.without.editing.confirm.single", modifiedWithoutEditing.iterator().next().getPresentableUrl())
|
||||
: VcsBundle.message("rollback.modified.without.editing.confirm.multiple", modifiedWithoutEditing.size());
|
||||
int rc = Messages.showYesNoDialog(project, message, VcsBundle.message("changes.action.rollback.title"), Messages.getQuestionIcon());
|
||||
if (rc != 0) {
|
||||
|
||||
+10
-2
@@ -6,17 +6,19 @@ import com.intellij.openapi.application.Application
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.testFramework.SkipInHeadlessEnvironment
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.plugins.gradle.testutil.ChangeBuilder
|
||||
import org.jetbrains.plugins.gradle.testutil.GradleProjectBuilder
|
||||
import org.jetbrains.plugins.gradle.testutil.IntellijProjectBuilder
|
||||
import org.jetbrains.plugins.gradle.testutil.ProjectStructureChecker
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.picocontainer.defaults.DefaultPicoContainer
|
||||
import org.jetbrains.plugins.gradle.diff.*
|
||||
import static org.junit.Assert.assertEquals
|
||||
import com.intellij.testFramework.SkipInHeadlessEnvironment
|
||||
import com.intellij.openapi.util.Disposer
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -32,6 +34,7 @@ public class GradleProjectStructureChangesModelTest {
|
||||
def changes
|
||||
def treeChecker
|
||||
def container
|
||||
Disposable disposable = [dispose: { }] as Disposable
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -50,7 +53,12 @@ public class GradleProjectStructureChangesModelTest {
|
||||
|
||||
changesModel = container.getComponentInstance(GradleProjectStructureChangesModel) as GradleProjectStructureChangesModel
|
||||
def applicationInfo = [getSmallIconUrl: {"/nodes/ideaProject.png"}] as ApplicationInfoEx
|
||||
ApplicationManager.setApplication([getComponent: { applicationInfo } ] as Application, [dispose: { }] as Disposable)
|
||||
ApplicationManager.setApplication([getComponent: { applicationInfo } ] as Application, disposable)
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+4
-4
@@ -85,7 +85,7 @@ public class GroovyCompletionData {
|
||||
|
||||
addTypeDefinitionKeywords(result, position);
|
||||
for (String keyword : addExtendsImplements(position)) {
|
||||
result.addElement(keyword(keyword, TailType.HUMBLE_SPACE));
|
||||
result.addElement(keyword(keyword, TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
|
||||
registerControlCompletion(position, result);
|
||||
@@ -93,7 +93,7 @@ public class GroovyCompletionData {
|
||||
if (parent instanceof GrExpression) {
|
||||
addKeywords(result, false, PsiKeyword.TRUE, PsiKeyword.FALSE, PsiKeyword.NULL, PsiKeyword.SUPER, PsiKeyword.THIS);
|
||||
result.addElement(keyword(PsiKeyword.NEW, TailType.INSERT_SPACE));
|
||||
result.addElement(keyword("as", TailType.HUMBLE_SPACE));
|
||||
result.addElement(keyword("as", TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
|
||||
if (isInfixOperatorPosition(position)) {
|
||||
@@ -146,7 +146,7 @@ public class GroovyCompletionData {
|
||||
addKeywords(result, true, PsiKeyword.CLASS, PsiKeyword.INTERFACE, PsiKeyword.ENUM);
|
||||
}
|
||||
if (afterAtInType(position)) {
|
||||
result.addElement(keyword(PsiKeyword.INTERFACE, TailType.HUMBLE_SPACE));
|
||||
result.addElement(keyword(PsiKeyword.INTERFACE, TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ public class GroovyCompletionData {
|
||||
|
||||
public static void addKeywords(CompletionResultSet result, boolean space, String... keywords) {
|
||||
for (String s : keywords) {
|
||||
result.addElement(keyword(s, space ? TailType.HUMBLE_SPACE : TailType.NONE));
|
||||
result.addElement(keyword(s, space ? TailType.HUMBLE_SPACE_BEFORE_WORD : TailType.NONE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -152,20 +152,20 @@ fromThis4
|
||||
fromThis5
|
||||
overridden
|
||||
thisProp
|
||||
class
|
||||
equals
|
||||
fromSuper
|
||||
fromSuper2
|
||||
metaPropertyValues
|
||||
properties
|
||||
superProp
|
||||
class
|
||||
equals
|
||||
getProperty
|
||||
hashCode
|
||||
invokeMethod
|
||||
metaClass
|
||||
metaPropertyValues
|
||||
notify
|
||||
notifyAll
|
||||
properties
|
||||
setProperty
|
||||
superProp
|
||||
toString
|
||||
wait
|
||||
wait
|
||||
|
||||
+2
-2
@@ -1064,7 +1064,7 @@ class X {
|
||||
}
|
||||
|
||||
public void testInnerClassStart() {
|
||||
checkSingleItemCompletion 'class Foo { cl<caret> }', 'class Foo { class<caret> }'
|
||||
checkSingleItemCompletion 'class Foo { cl<caret> }', 'class Foo { class <caret> }'
|
||||
}
|
||||
|
||||
public void testPropertyBeforeAccessor() {
|
||||
@@ -1115,7 +1115,7 @@ public class KeyVO {
|
||||
public void testSpaceTail() {
|
||||
checkCompletion 'class A <caret> ArrayList {}', ' ', 'class A extends <caret> ArrayList {}'
|
||||
checkCompletion 'class A <caret> ArrayList {}', '\n', 'class A extends<caret> ArrayList {}'
|
||||
checkSingleItemCompletion 'class Foo impl<caret> {}', 'class Foo implements<caret> {}'
|
||||
checkSingleItemCompletion 'class Foo impl<caret> {}', 'class Foo implements <caret> {}'
|
||||
}
|
||||
|
||||
public void testPreferInterfacesInImplements() {
|
||||
|
||||
+49
-5
@@ -41,6 +41,8 @@ public class GridInsertLocation extends GridDropLocation {
|
||||
|
||||
private GridInsertMode myMode;
|
||||
|
||||
private boolean mySpanInsertMode;
|
||||
|
||||
public GridInsertLocation(@NotNull final RadContainer container,
|
||||
final int row,
|
||||
final int column,
|
||||
@@ -82,6 +84,10 @@ public class GridInsertLocation extends GridDropLocation {
|
||||
return myMode;
|
||||
}
|
||||
|
||||
public void setSpanInsertMode(boolean spanInsertMode) {
|
||||
mySpanInsertMode = spanInsertMode;
|
||||
}
|
||||
|
||||
private boolean isColumnInsert() {
|
||||
return myMode == GridInsertMode.ColumnAfter || myMode == GridInsertMode.ColumnBefore;
|
||||
}
|
||||
@@ -198,7 +204,7 @@ public class GridInsertLocation extends GridDropLocation {
|
||||
int cellWidth = vGridLines [lastColIndex] - vGridLines [insertCol];
|
||||
int cellHeight = hGridLines [lastRowIndex] - hGridLines [insertRow];
|
||||
RadComponent component = layoutManager.getComponentAtGrid(getContainer(), insertRow, insertCol);
|
||||
if (component != null) {
|
||||
if (component != null && mySpanInsertMode) {
|
||||
Rectangle bounds = component.getBounds();
|
||||
bounds.translate(-vGridLines [insertCol], -hGridLines [insertRow]);
|
||||
|
||||
@@ -217,6 +223,32 @@ public class GridInsertLocation extends GridDropLocation {
|
||||
rcFeedback = new Rectangle(bounds.x + bounds.width, 0, spaceToRight, cellHeight);
|
||||
}
|
||||
|
||||
if (rcFeedback != null) {
|
||||
boolean spanInsertMode = false;
|
||||
|
||||
if (isRowInsert()) {
|
||||
int columns = layoutManager.getGridColumnCount(getContainer());
|
||||
for (int i = 0; i < columns; i++) {
|
||||
if (i != insertCol && RadAbstractGridLayoutManager.getComponentAtGrid(getContainer(), insertRow, i) != null) {
|
||||
spanInsertMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int rows = layoutManager.getGridRowCount(getContainer());
|
||||
for (int i = 0; i < rows; i++) {
|
||||
if (i != insertRow && RadAbstractGridLayoutManager.getComponentAtGrid(getContainer(), i, insertCol) != null) {
|
||||
spanInsertMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!spanInsertMode) {
|
||||
rcFeedback = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (rcFeedback != null) {
|
||||
rcFeedback.translate(vGridLines [insertCol], hGridLines [insertRow]);
|
||||
}
|
||||
@@ -336,13 +368,17 @@ public class GridInsertLocation extends GridDropLocation {
|
||||
int cellsToInsert = 1;
|
||||
if (components.length > 0) {
|
||||
int cellSize = container.getGridCellCount(isRowInsert());
|
||||
Rectangle rc = getDragObjectDimensions(dragObject, cell < cellSize - 1);
|
||||
int size = isRowInsert() ? rc.height : rc.width;
|
||||
if (size > 0) {
|
||||
cellsToInsert = size;
|
||||
Rectangle rc = getDragObjectDimensions(dragObject, cell < cellSize - 1);
|
||||
int size = isRowInsert() ? rc.height : rc.width;
|
||||
if (size > 0) {
|
||||
cellsToInsert = size;
|
||||
}
|
||||
}
|
||||
|
||||
GridSpanInsertProcessor spanInsertProcessor =
|
||||
mySpanInsertMode && dragObject.getComponentCount() == 1 ? new GridSpanInsertProcessor(container, getRow(), getColumn(), myMode,
|
||||
dragObject) : null;
|
||||
|
||||
int newCell = insertGridCells(container, cell, cellsToInsert, canGrow, isRowInsert(), !isInsertAfter(), constraintsToAdjust);
|
||||
if (isRowInsert()) {
|
||||
row = newCell;
|
||||
@@ -352,7 +388,15 @@ public class GridInsertLocation extends GridDropLocation {
|
||||
}
|
||||
|
||||
if (components.length > 0) {
|
||||
if (spanInsertProcessor != null) {
|
||||
spanInsertProcessor.doBefore(newCell);
|
||||
}
|
||||
|
||||
dropIntoGrid(container, components, row, col, dragObject);
|
||||
|
||||
if (spanInsertProcessor != null) {
|
||||
spanInsertProcessor.doAfter(newCell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.uiDesigner.designSurface;
|
||||
|
||||
import com.intellij.uiDesigner.core.GridConstraints;
|
||||
import com.intellij.uiDesigner.radComponents.RadAbstractGridLayoutManager;
|
||||
import com.intellij.uiDesigner.radComponents.RadComponent;
|
||||
import com.intellij.uiDesigner.radComponents.RadContainer;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class GridSpanInsertProcessor {
|
||||
private final RadContainer myContainer;
|
||||
private final RadAbstractGridLayoutManager myLayoutManager;
|
||||
private final int myRow;
|
||||
private final int myColumn;
|
||||
private GridInsertMode myMode;
|
||||
private RadComponent myInsertCellComponent;
|
||||
|
||||
public GridSpanInsertProcessor(RadContainer container,
|
||||
int insertRow,
|
||||
int insertColumn,
|
||||
GridInsertMode mode,
|
||||
ComponentDragObject dragObject) {
|
||||
myContainer = container;
|
||||
myLayoutManager = container.getGridLayoutManager();
|
||||
myRow = insertRow;
|
||||
myColumn = insertColumn;
|
||||
|
||||
int[] vGridLines = myLayoutManager.getVerticalGridLines(container);
|
||||
int[] hGridLines = myLayoutManager.getHorizontalGridLines(container);
|
||||
|
||||
RadComponent component = RadAbstractGridLayoutManager.getComponentAtGrid(container, insertRow, insertColumn);
|
||||
|
||||
if (component != null) {
|
||||
int lastColIndex = insertColumn + dragObject.getColSpan(0);
|
||||
if (lastColIndex > vGridLines.length - 1) {
|
||||
lastColIndex = insertColumn + 1;
|
||||
}
|
||||
|
||||
int lastRowIndex = insertRow + dragObject.getRowSpan(0);
|
||||
if (lastRowIndex > hGridLines.length - 1) {
|
||||
lastRowIndex = insertRow + 1;
|
||||
}
|
||||
|
||||
Rectangle bounds = component.getBounds();
|
||||
bounds.translate(-vGridLines[insertColumn], -hGridLines[insertRow]);
|
||||
|
||||
int spaceToRight = vGridLines[lastColIndex] - vGridLines[insertColumn] - (bounds.x + bounds.width);
|
||||
int spaceBelow = hGridLines[lastRowIndex] - hGridLines[insertRow] - (bounds.y + bounds.height);
|
||||
|
||||
if (mode == GridInsertMode.RowBefore && bounds.y > GridInsertLocation.INSERT_RECT_MIN_SIZE) {
|
||||
myMode = GridInsertMode.RowBefore;
|
||||
myInsertCellComponent = component;
|
||||
}
|
||||
else if (mode == GridInsertMode.RowAfter && spaceBelow > GridInsertLocation.INSERT_RECT_MIN_SIZE) {
|
||||
myMode = GridInsertMode.RowAfter;
|
||||
}
|
||||
else if (mode == GridInsertMode.ColumnBefore && bounds.x > GridInsertLocation.INSERT_RECT_MIN_SIZE) {
|
||||
myMode = GridInsertMode.ColumnBefore;
|
||||
myInsertCellComponent = component;
|
||||
}
|
||||
else if (mode == GridInsertMode.ColumnAfter && spaceToRight > GridInsertLocation.INSERT_RECT_MIN_SIZE) {
|
||||
myMode = GridInsertMode.ColumnAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doBefore(int newCell) {
|
||||
if (myMode == GridInsertMode.RowBefore) {
|
||||
int oldRow = myInsertCellComponent.getConstraints().getRow();
|
||||
int columns = myLayoutManager.getGridColumnCount(myContainer);
|
||||
for (int i = 0; i < columns; i++) {
|
||||
if (i != myColumn) {
|
||||
RadComponent component = RadAbstractGridLayoutManager.getComponentAtGrid(myContainer, oldRow, i);
|
||||
if (component != null) {
|
||||
GridConstraints constraints = component.getConstraints();
|
||||
|
||||
if (constraints.getRow() == oldRow) {
|
||||
GridConstraints oldConstraints = (GridConstraints)constraints.clone();
|
||||
constraints.setRow(newCell);
|
||||
constraints.setRowSpan(constraints.getRowSpan() + oldRow - newCell);
|
||||
component.fireConstraintsChanged(oldConstraints);
|
||||
}
|
||||
|
||||
i = constraints.getColumn() + constraints.getColSpan() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myMode == GridInsertMode.ColumnBefore) {
|
||||
int oldColumn = myInsertCellComponent.getConstraints().getColumn();
|
||||
int rows = myLayoutManager.getGridRowCount(myContainer);
|
||||
for (int i = 0; i < rows; i++) {
|
||||
if (i != myRow) {
|
||||
RadComponent component = RadAbstractGridLayoutManager.getComponentAtGrid(myContainer, i, oldColumn);
|
||||
if (component != null) {
|
||||
GridConstraints constraints = component.getConstraints();
|
||||
|
||||
if (constraints.getColumn() == oldColumn) {
|
||||
GridConstraints oldConstraints = (GridConstraints)constraints.clone();
|
||||
constraints.setColumn(newCell);
|
||||
constraints.setColSpan(constraints.getColSpan() + oldColumn - newCell);
|
||||
component.fireConstraintsChanged(oldConstraints);
|
||||
}
|
||||
|
||||
i = constraints.getRow() + constraints.getRowSpan() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doAfter(int newCell) {
|
||||
if (myMode == GridInsertMode.RowAfter) {
|
||||
int columns = myLayoutManager.getGridColumnCount(myContainer);
|
||||
for (int i = 0; i < columns; i++) {
|
||||
if (i != myColumn) {
|
||||
RadComponent component = RadAbstractGridLayoutManager.getComponentAtGrid(myContainer, myRow, i);
|
||||
if (component != null) {
|
||||
GridConstraints constraints = component.getConstraints();
|
||||
int endRow = constraints.getRow() + constraints.getRowSpan() - 1;
|
||||
|
||||
if (endRow == myRow) {
|
||||
GridConstraints oldConstraints = (GridConstraints)constraints.clone();
|
||||
constraints.setRowSpan(constraints.getRowSpan() + newCell - myRow);
|
||||
component.fireConstraintsChanged(oldConstraints);
|
||||
}
|
||||
|
||||
i = constraints.getColumn() + constraints.getColSpan() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myMode == GridInsertMode.ColumnAfter) {
|
||||
int rows = myLayoutManager.getGridRowCount(myContainer);
|
||||
for (int i = 0; i < rows; i++) {
|
||||
if (i != myRow) {
|
||||
RadComponent component = RadAbstractGridLayoutManager.getComponentAtGrid(myContainer, i, myColumn);
|
||||
if (component != null) {
|
||||
GridConstraints constraints = component.getConstraints();
|
||||
int endColumn = constraints.getColumn() + constraints.getColSpan() - 1;
|
||||
|
||||
if (endColumn == myColumn) {
|
||||
GridConstraints oldConstraints = (GridConstraints)constraints.clone();
|
||||
constraints.setColSpan(constraints.getColSpan() + newCell - myColumn);
|
||||
component.fireConstraintsChanged(oldConstraints);
|
||||
}
|
||||
|
||||
i = constraints.getRow() + constraints.getRowSpan() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -190,6 +190,10 @@ public abstract class RadAbstractGridLayoutManager extends RadLayoutManager {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean canSpanningAllowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean canResizeCells() {
|
||||
return true;
|
||||
}
|
||||
@@ -301,6 +305,8 @@ public abstract class RadAbstractGridLayoutManager extends RadLayoutManager {
|
||||
mode = GridInsertMode.ColumnAfter;
|
||||
}
|
||||
|
||||
boolean spanInsertMode = canSpanningAllowed() && mode == null;
|
||||
boolean normalize = true;
|
||||
final int cellWidth = vertGridLines[col + 1] - vertGridLines[col];
|
||||
final int cellHeight = horzGridLines[row + 1] - horzGridLines[row];
|
||||
if (mode == null) {
|
||||
@@ -324,11 +330,15 @@ public abstract class RadAbstractGridLayoutManager extends RadLayoutManager {
|
||||
else if (dx > right && dx < cellWidth) {
|
||||
mode = GridInsertMode.ColumnAfter;
|
||||
}
|
||||
|
||||
normalize = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode != null) {
|
||||
return new GridInsertLocation(container, row, col, mode).normalize();
|
||||
GridInsertLocation dropLocation = new GridInsertLocation(container, row, col, mode);
|
||||
dropLocation.setSpanInsertMode(spanInsertMode);
|
||||
return normalize ? dropLocation.normalize() : dropLocation;
|
||||
}
|
||||
if (getComponentAtGrid(container, row, col) instanceof RadVSpacer ||
|
||||
getComponentAtGrid(container, row, col) instanceof RadHSpacer) {
|
||||
|
||||
+51
-3
@@ -111,6 +111,31 @@ public class GridInsertLocationTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testInsertGrowMultiple() {
|
||||
setGridSize(4, 4);
|
||||
|
||||
// * . . .
|
||||
// . . . .
|
||||
// . . . .
|
||||
// . . . *
|
||||
|
||||
insertComponent(0, 0, 1, 1);
|
||||
insertComponent(3, 3, 1, 1);
|
||||
|
||||
// * . . .
|
||||
// . . . .
|
||||
// * . . .
|
||||
// * . . *
|
||||
RadComponent c1 = createComponent(0, 0, 2, 1);
|
||||
RadComponent c2 = createComponent(0, 1, 1, 1);
|
||||
|
||||
GridInsertLocation location = new GridInsertLocation(myContainer, 1, 0, GridInsertMode.RowAfter);
|
||||
DraggedComponentList dcl = DraggedComponentList.withComponents(c1, c2);
|
||||
assertTrue(location.canDrop(dcl));
|
||||
location.processDrop(null, new RadComponent[] {c1, c2}, null, dcl);
|
||||
assertEquals(6, myManager.getGridRowCount(myContainer));
|
||||
}
|
||||
|
||||
public void testInsertGrowMultiple1x1() {
|
||||
setGridSize(2, 2);
|
||||
|
||||
// * .
|
||||
@@ -130,10 +155,10 @@ public class GridInsertLocationTest extends TestCase {
|
||||
DraggedComponentList dcl = DraggedComponentList.withComponents(c1, c2);
|
||||
assertTrue(location.canDrop(dcl));
|
||||
location.processDrop(null, new RadComponent[] {c1, c2}, null, dcl);
|
||||
assertEquals(4, myManager.getGridRowCount(myContainer));
|
||||
assertEquals(3, myManager.getGridRowCount(myContainer));
|
||||
}
|
||||
|
||||
public void testInsertGrowSingle() {
|
||||
public void testInsertGrowSingle1x1() {
|
||||
setGridSize(2, 2);
|
||||
|
||||
// * .
|
||||
@@ -148,7 +173,30 @@ public class GridInsertLocationTest extends TestCase {
|
||||
DraggedComponentList dcl = DraggedComponentList.withComponents(myDropComponent);
|
||||
assertTrue(location.canDrop(dcl));
|
||||
doDrop(location);
|
||||
assertEquals(4, myManager.getGridRowCount(myContainer));
|
||||
assertEquals(3, myManager.getGridRowCount(myContainer));
|
||||
final RadComponent addedComponent = myContainer.getComponents()[2];
|
||||
assertEquals(1, addedComponent.getConstraints().getRowSpan());
|
||||
assertEquals(1, addedComponent.getConstraints().getColSpan());
|
||||
|
||||
}
|
||||
|
||||
public void testInsertGrowSingle() {
|
||||
setGridSize(4, 4);
|
||||
|
||||
// * . . .
|
||||
// . . . .
|
||||
// . . . .
|
||||
// . . . *
|
||||
|
||||
insertComponent(0, 0, 1, 1);
|
||||
insertComponent(3, 3, 1, 1);
|
||||
|
||||
setComponentDimensions(myDropComponent, 0, 0, 2, 2);
|
||||
GridInsertLocation location = new GridInsertLocation(myContainer, 1, 0, GridInsertMode.RowAfter);
|
||||
DraggedComponentList dcl = DraggedComponentList.withComponents(myDropComponent);
|
||||
assertTrue(location.canDrop(dcl));
|
||||
doDrop(location);
|
||||
assertEquals(6, myManager.getGridRowCount(myContainer));
|
||||
final RadComponent addedComponent = myContainer.getComponents()[2];
|
||||
assertEquals(2, addedComponent.getConstraints().getRowSpan());
|
||||
assertEquals(2, addedComponent.getConstraints().getColSpan());
|
||||
|
||||
Reference in New Issue
Block a user