/* * Copyright 2013-2016 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.unity3d.csharp.completion; import java.util.Map; import org.jetbrains.annotations.NotNull; import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.InsertHandler; import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.icons.AllIcons; import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.psi.PsiElement; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import consulo.annotations.RequiredDispatchThread; import consulo.annotations.RequiredReadAction; import consulo.csharp.ide.completion.CSharpMemberAddByCompletionContributor; import consulo.csharp.lang.psi.CSharpMethodDeclaration; import consulo.csharp.lang.psi.CSharpTypeDeclaration; import consulo.csharp.lang.psi.CSharpTypeRefPresentationUtil; import consulo.csharp.lang.psi.impl.source.CSharpBlockStatementImpl; import consulo.dotnet.psi.DotNetInheritUtil; import consulo.dotnet.psi.DotNetStatement; import consulo.dotnet.psi.DotNetVirtualImplementOwner; import consulo.dotnet.resolve.DotNetTypeRef; import consulo.ide.IconDescriptor; import consulo.unity3d.Unity3dIcons; import consulo.unity3d.csharp.UnityFunctionManager; import consulo.unity3d.module.Unity3dModuleExtension; /** * @author VISTALL * @since 19.12.14 */ public class UnitySpecificMethodCompletion extends CSharpMemberAddByCompletionContributor { @RequiredReadAction @Override public void processCompletion(@NotNull CompletionParameters completionParameters, @NotNull ProcessingContext processingContext, @NotNull Consumer<LookupElement> completionResultSet, @NotNull CSharpTypeDeclaration typeDeclaration) { Unity3dModuleExtension extension = ModuleUtilCore.getExtension(typeDeclaration, Unity3dModuleExtension.class); if(extension == null) { return; } for(Map.Entry<String, Map<String, UnityFunctionManager.FunctionInfo>> entry : UnityFunctionManager.getInstance().getFunctionsByType().entrySet()) { String typeName = entry.getKey(); if(!DotNetInheritUtil.isParent(typeName, typeDeclaration, true)) { continue; } for(UnityFunctionManager.FunctionInfo functionInfo : entry.getValue().values()) { UnityFunctionManager.FunctionInfo nonParameterListCopy = functionInfo.createNonParameterListCopy(); if(nonParameterListCopy != null) { completionResultSet.consume(buildLookupItem(nonParameterListCopy, typeDeclaration)); } completionResultSet.consume(buildLookupItem(functionInfo, typeDeclaration)); } } } @NotNull @RequiredReadAction private static LookupElementBuilder buildLookupItem(UnityFunctionManager.FunctionInfo functionInfo, CSharpTypeDeclaration scope) { StringBuilder builder = new StringBuilder(); builder.append("void "); builder.append(functionInfo.getName()); builder.append("("); boolean first = true; for(Map.Entry<String, String> entry : functionInfo.getParameters().entrySet()) { if(first) { first = false; } else { builder.append(", "); } DotNetTypeRef typeRef = UnityFunctionManager.createTypeRef(scope, entry.getKey()); builder.append(CSharpTypeRefPresentationUtil.buildShortText(typeRef, scope)); builder.append(" "); builder.append(entry.getKey()); } builder.append(")"); String presentationText = builder.toString(); builder.append("{\n"); builder.append("}"); LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(builder.toString()); lookupElementBuilder = lookupElementBuilder.withPresentableText(presentationText); lookupElementBuilder = lookupElementBuilder.withLookupString(functionInfo.getName()); lookupElementBuilder = lookupElementBuilder.withTailText("{...}", true); IconDescriptor iconDescriptor = new IconDescriptor(new IconDescriptor(AllIcons.Nodes.Method).toIcon()); iconDescriptor.setRightIcon(Unity3dIcons.EventMethod); lookupElementBuilder = lookupElementBuilder.withIcon(iconDescriptor.toIcon()); lookupElementBuilder = lookupElementBuilder.withInsertHandler(new InsertHandler<LookupElement>() { @Override @RequiredDispatchThread public void handleInsert(InsertionContext context, LookupElement item) { CaretModel caretModel = context.getEditor().getCaretModel(); PsiElement elementAt = context.getFile().findElementAt(caretModel.getOffset() - 1); if(elementAt == null) { return; } DotNetVirtualImplementOwner virtualImplementOwner = PsiTreeUtil.getParentOfType(elementAt, DotNetVirtualImplementOwner.class); if(virtualImplementOwner == null) { return; } if(virtualImplementOwner instanceof CSharpMethodDeclaration) { PsiElement codeBlock = ((CSharpMethodDeclaration) virtualImplementOwner).getCodeBlock(); if(codeBlock instanceof CSharpBlockStatementImpl) { DotNetStatement[] statements = ((CSharpBlockStatementImpl) codeBlock).getStatements(); if(statements.length > 0) { caretModel.moveToOffset(statements[0].getTextOffset() + statements[0].getTextLength()); } else { caretModel.moveToOffset(((CSharpBlockStatementImpl) codeBlock).getLeftBrace().getTextOffset() + 1); } } } context.commitDocument(); CodeStyleManager.getInstance(context.getProject()).reformat(virtualImplementOwner); } }); return lookupElementBuilder; } }