/* * 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.shaderlab.ide.completion; import java.util.Collection; import org.jetbrains.annotations.NotNull; import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.CompletionContributor; import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.CompletionType; 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.openapi.editor.Caret; import com.intellij.openapi.project.Project; import com.intellij.patterns.StandardPatterns; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ProcessingContext; import com.intellij.util.Processor; import consulo.annotations.RequiredReadAction; import consulo.codeInsight.completion.CompletionProvider; import consulo.csharp.ide.completion.util.SpaceInsertHandler; import consulo.unity3d.shaderlab.lang.ShaderLabFileType; import consulo.unity3d.shaderlab.lang.ShaderLabPropertyType; import consulo.unity3d.shaderlab.lang.parser.roles.ShaderLabCompositeRole; import consulo.unity3d.shaderlab.lang.parser.roles.ShaderLabRole; import consulo.unity3d.shaderlab.lang.parser.roles.ShaderLabSimpleRole; import consulo.unity3d.shaderlab.lang.psi.ShaderBraceOwner; import consulo.unity3d.shaderlab.lang.psi.ShaderDef; import consulo.unity3d.shaderlab.lang.psi.ShaderLabKeyTokens; import consulo.unity3d.shaderlab.lang.psi.ShaderLabTokens; import consulo.unity3d.shaderlab.lang.psi.ShaderPropertyTypeElement; import consulo.unity3d.shaderlab.lang.psi.ShaderSimpleValue; import consulo.unity3d.shaderlab.lang.psi.stub.index.ShaderDefIndex; /** * @author VISTALL * @since 08.05.2015 */ public class ShaderLabCompletionContributor extends CompletionContributor { public ShaderLabCompletionContributor() { extend(CompletionType.BASIC, StandardPatterns.psiElement(ShaderLabTokens.IDENTIFIER).withParent(ShaderPropertyTypeElement.class), new CompletionProvider() { @RequiredReadAction @Override public void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) { for(ShaderLabPropertyType shaderLabPropertyType : ShaderLabPropertyType.values()) { LookupElementBuilder builder = LookupElementBuilder.create(shaderLabPropertyType.getPresentableName()); builder = builder.bold(); result.addElement(builder); } } }); extend(CompletionType.BASIC, StandardPatterns.psiElement().withParent(ShaderBraceOwner.class), new CompletionProvider() { @RequiredReadAction @Override public void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) { ShaderBraceOwner braceOwner = PsiTreeUtil.getParentOfType(parameters.getPosition(), ShaderBraceOwner.class); if(braceOwner == null) { return; } ShaderLabRole role = braceOwner.getRole(); if(!(role instanceof ShaderLabCompositeRole)) { return; } for(final ShaderLabRole labRole : ((ShaderLabCompositeRole) role).getRoles()) { LookupElementBuilder builder = LookupElementBuilder.create(labRole.getName()); if(labRole instanceof ShaderLabCompositeRole) { builder = builder.withInsertHandler(BracesInsertHandler.INSTANCE); } else { final String defaultInsertValue = labRole.getDefaultInsertValue(); if(defaultInsertValue == null) { builder = builder.withInsertHandler(SpaceInsertHandler.INSTANCE); } else { builder = builder.withInsertHandler(new InsertHandler<LookupElement>() { @Override public void handleInsert(InsertionContext context, LookupElement item) { int offset = context.getTailOffset(); offset = TailType.insertChar(context.getEditor(), offset, ' '); context.getDocument().insertString(offset, defaultInsertValue); Caret currentCaret = context.getEditor().getCaretModel().getCurrentCaret(); currentCaret.setSelection(offset, offset + defaultInsertValue.length()); } }); } } result.addElement(builder); } } }); extend(CompletionType.BASIC, StandardPatterns.psiElement().afterLeaf(StandardPatterns.psiElement().withElementType(ShaderLabKeyTokens.START_KEYWORD)), new CompletionProvider() { @RequiredReadAction @Override public void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull final CompletionResultSet result) { ShaderSimpleValue simpleValue = PsiTreeUtil.getParentOfType(parameters.getPosition(), ShaderSimpleValue.class); if(simpleValue == null) { return; } ShaderLabRole role = simpleValue.getRole(); if(role == null || role != ShaderLabRole.Fallback && role != ShaderLabRole.UsePass) { return; } final Project project = parameters.getPosition().getProject(); ShaderDefIndex.getInstance().processAllKeys(project, new Processor<String>() { @Override public boolean process(String s) { Collection<ShaderDef> shaderDefs = ShaderDefIndex.getInstance().get(s, project, GlobalSearchScope.projectScope(project)); if(shaderDefs.isEmpty()) { return true; } LookupElementBuilder builder = LookupElementBuilder.create(s); builder = builder.withIcon(ShaderLabFileType.INSTANCE.getIcon()); result.addElement(builder); return true; } }); String defaultInsertValue = role.getDefaultInsertValue(); if(defaultInsertValue != null) { result.addElement(LookupElementBuilder.create(defaultInsertValue).bold()); } } }); extend(CompletionType.BASIC, StandardPatterns.psiElement().afterLeaf(StandardPatterns.psiElement().withElementType(ShaderLabKeyTokens.START_KEYWORD)), new CompletionProvider() { @RequiredReadAction @Override public void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull final CompletionResultSet result) { ShaderSimpleValue simpleValue = PsiTreeUtil.getParentOfType(parameters.getPosition(), ShaderSimpleValue.class); if(simpleValue == null) { return; } ShaderLabRole role = simpleValue.getRole(); if(!(role instanceof ShaderLabSimpleRole)) { return; } for(String value : ((ShaderLabSimpleRole) role).getValues()) { LookupElementBuilder builder = LookupElementBuilder.create(value); builder = builder.bold(); result.addElement(builder); } } }); } }