/*
* Copyright 2013-2017 consulo.io
*
* 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 consulo.csharp.ide.completion.item;
import org.jetbrains.annotations.NotNull;
import consulo.annotations.RequiredReadAction;
import consulo.annotations.RequiredWriteAction;
import consulo.csharp.ide.completion.CSharpCompletionSorting;
import consulo.csharp.lang.psi.CSharpConstructorDeclaration;
import consulo.csharp.lang.psi.CSharpMethodUtil;
import consulo.csharp.lang.psi.CSharpNewExpression;
import consulo.csharp.lang.psi.CSharpTypeDeclaration;
import consulo.csharp.lang.psi.CSharpUserType;
import consulo.csharp.lang.psi.impl.msil.MsilMethodAsCSharpMethodDeclaration;
import consulo.dotnet.psi.DotNetNamedElement;
import consulo.dotnet.psi.DotNetQualifiedElement;
import consulo.dotnet.resolve.DotNetGenericExtractor;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
/**
* @author VISTALL
* @since 28.07.2015
*/
public class CSharpTypeLikeLookupElement extends LookupElementDecorator<LookupElement>
{
@NotNull
public static CSharpTypeLikeLookupElement create(LookupElement delegate, DotNetGenericExtractor extractor, PsiElement expression)
{
CSharpNewExpression newExpression = null;
PsiElement parent = expression == null ? null : expression.getParent();
if(parent instanceof CSharpUserType)
{
PsiElement typeParent = parent.getParent();
if(typeParent instanceof CSharpNewExpression)
{
newExpression = (CSharpNewExpression) typeParent;
}
}
return new CSharpTypeLikeLookupElement(delegate, extractor, newExpression != null);
}
private DotNetGenericExtractor myExtractor;
private boolean myAfterNew;
public CSharpTypeLikeLookupElement(LookupElement delegate, DotNetGenericExtractor extractor, boolean afterNew)
{
super(delegate);
myExtractor = extractor;
myAfterNew = afterNew;
PsiElement psiElement = delegate.getPsiElement();
assert psiElement instanceof DotNetQualifiedElement;
CSharpCompletionSorting.copyForce(delegate, this);
}
@Override
@RequiredWriteAction
public void handleInsert(InsertionContext context)
{
super.handleInsert(context);
if(myAfterNew)
{
context.commitDocument();
PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(context.getDocument());
boolean hasParameters = false;
if(myExtractor != DotNetGenericExtractor.EMPTY)
{
PsiElement psiElement = getPsiElement();
if(psiElement instanceof CSharpTypeDeclaration)
{
DotNetNamedElement[] members = ((CSharpTypeDeclaration) psiElement).getMembers();
for(DotNetNamedElement member : members)
{
if(member instanceof CSharpConstructorDeclaration)
{
int length = ((CSharpConstructorDeclaration) member).getParameters().length;
if(length > 0)
{
hasParameters = true;
break;
}
}
}
}
else if(CSharpMethodUtil.isDelegate(psiElement))
{
hasParameters = true;
}
}
CaretModel caretModel = context.getEditor().getCaretModel();
int oldCaretOffset = caretModel.getOffset();
ParenthesesInsertHandler.getInstance(true).handleInsert(context, this);
if(!hasParameters)
{
caretModel.moveToOffset(oldCaretOffset + 2);
}
}
}
@Override
@RequiredReadAction
public boolean equals(Object o)
{
if(this == o)
{
return true;
}
if(o == null || getClass() != o.getClass())
{
return false;
}
return Comparing.equal(getOriginal().getPresentableQName(), ((CSharpTypeLikeLookupElement) o).getOriginal().getPresentableQName());
}
@Override
public int hashCode()
{
return getOriginal().hashCode();
}
@NotNull
public DotNetGenericExtractor getExtractor()
{
return myExtractor;
}
@NotNull
private DotNetQualifiedElement getOriginal()
{
LookupElement delegate = getDelegate();
PsiElement psiElement = delegate.getPsiElement();
assert psiElement != null;
if(psiElement instanceof MsilMethodAsCSharpMethodDeclaration)
{
return ((MsilMethodAsCSharpMethodDeclaration) psiElement).getDelegate();
}
return (DotNetQualifiedElement) psiElement.getOriginalElement();
}
}