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

This commit is contained in:
Dmitry Boulytchev (dboulytchev@gmail.com)
2012-02-02 01:24:44 +04:00
37 changed files with 643 additions and 321 deletions
@@ -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());
@@ -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);
}
}
@@ -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);
@@ -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> {
}
@@ -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>
}
}
@@ -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 {
@@ -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 {}");
@@ -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('.');
@@ -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);
}
@@ -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));
}
@@ -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, "&nbsp;", " ");
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), "&nbsp;", " ");
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&nbsp;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)]
}
}
@@ -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());
}
@@ -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) {
@@ -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
@@ -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));
}
}
@@ -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
@@ -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() {
@@ -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);
}
}
}
@@ -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;
}
}
}
}
}
}
@@ -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) {
@@ -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());