/* * Copyright 2013 original Randori IntelliJ Plugin authors. * * 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 randori.plugin.lang.css; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.patterns.ElementPattern; import com.intellij.psi.PsiElement; import com.intellij.psi.css.CssDeclaration; import com.intellij.util.ProcessingContext; import org.apache.flex.compiler.definitions.IClassDefinition; import org.apache.flex.compiler.definitions.ITypeDefinition; import org.jetbrains.annotations.NotNull; import randori.compiler.access.IASProjectAccess; import randori.compiler.internal.projects.RandoriProject; import randori.plugin.compiler.RandoriCompilerSession; import randori.plugin.util.ProjectUtils; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import static com.intellij.patterns.PlatformPatterns.psiElement; /** * @author Roland Zwaga <roland@stackandheap.com> */ public class RandoriCSSSCompletionContributor extends CompletionContributor { private static final Logger logger = Logger.getInstance(RandoriCSSSCompletionContributor.class); private static final ElementPattern<PsiElement> AFTER_DOUBLE_COLON = psiElement().afterLeaf(":"); private static final String RANDORI_PREFIX = "-randori"; private static final Map<String, String> superClassLookup; static { Map<String, String> tempMap = new HashMap<String, String>(); tempMap.put(RANDORI_PREFIX + "-behavior", "randori.behaviors.AbstractBehavior"); tempMap.put(RANDORI_PREFIX + "-mediator", "randori.behaviors.AbstractMediator"); tempMap.put(RANDORI_PREFIX + "-context", "guice.GuiceModule"); superClassLookup = Collections.unmodifiableMap(tempMap); } public RandoriCSSSCompletionContributor() { final Project project = ProjectUtils.getProject(); if (project != null) { extend(CompletionType.BASIC, AFTER_DOUBLE_COLON, new CompletionProvider<CompletionParameters>() { @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) { if (!ProjectUtils.hasRandoriModuleType(project)) { logger.debug("No Randori project active, bailing out"); return; } final PsiElement position = parameters.getPosition(); final CssDeclaration declaration = getCssDeclaration(position); if (declaration != null) { String name = declaration.getPropertyName(); if (isRandoriCSSDeclaration(name)) { String superClass = getSuperClassNameForCSSDeclaration(name); if (superClass != null) { RandoriProject compiler = RandoriCompilerSession.getLastCompiler(); if (compiler != null) { IASProjectAccess projectAccess = compiler.getProjectAccess(); if (projectAccess != null) { Collection<IClassDefinition> subClasses = getSubClasses(superClass, projectAccess); if (subClasses != null) { addLookupElements(subClasses, result); } result.stopHere(); } } } } } } }); } } private void addLookupElements(Collection<IClassDefinition> subClasses, CompletionResultSet result) { for (final IClassDefinition subClass : subClasses) { result.addElement(new LookupElement() { @NotNull @Override public String getLookupString() { return '"' + subClass.getQualifiedName() + '"'; } @Override public void renderElement(LookupElementPresentation presentation) { presentation.setItemText(subClass.getQualifiedName()); } }); } } private Collection<IClassDefinition> getSubClasses(String superClass, IASProjectAccess projectAccess) { ITypeDefinition typeDefinition = projectAccess.getType(superClass); if ((typeDefinition != null) && (typeDefinition instanceof IClassDefinition)) { return projectAccess.getSubClasses((IClassDefinition) typeDefinition); } return null; } private String getSuperClassNameForCSSDeclaration(String name) { if (superClassLookup.containsKey(name)) { return superClassLookup.get(name); } logger.error("Unrecognized Randori CSS declaration: " + name); return null; } private boolean isRandoriCSSDeclaration(String name) { return name.startsWith(RANDORI_PREFIX); } private CssDeclaration getCssDeclaration(PsiElement position) { CssDeclaration decl = null; PsiElement elm = position.getParent(); while (elm != null) { if (elm instanceof CssDeclaration) { decl = (CssDeclaration) elm; break; } elm = elm.getParent(); } return decl; } }