/* * 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.lookup.LookupElementBuilder; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.css.*; import org.apache.flex.compiler.definitions.IClassDefinition; import org.apache.flex.compiler.definitions.ITypeDefinition; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import randori.compiler.access.IASProjectAccess; import randori.compiler.internal.projects.RandoriProject; import randori.plugin.compiler.RandoriCompilerSession; import randori.plugin.configuration.RandoriCompilerModel; import java.util.ArrayList; import java.util.Collection; import java.util.Map; /** * @author Roland Zwaga <roland@stackandheap.com> */ public class RandoriCssPropertyDescriptor implements CssPropertyDescriptor { public static final String HTML_EXT = "html"; public static final String HTM_EXT = "htm"; public RandoriCssPropertyDescriptor(@NotNull String name, @NotNull Map<String, String> superClassLookup) { _propertyName = name; _superClassLookup = superClassLookup; } final private String _propertyName; final private Map<String, String> _superClassLookup; @Nullable @Override public String generateDoc(PsiElement context) { return _propertyName + " is a Randori specific CSS property"; } @Override public boolean isValidValue(@NotNull PsiElement element) { boolean result = true; if (element instanceof CssTerm) { CssTerm term = (CssTerm) element; String txt = term.getText(); result = ((txt.startsWith("\"")) && (txt.endsWith("\""))); if ((result) && (!_propertyName.equals("-randori-fragment"))) { final RandoriCompilerModel model = RandoriCompilerModel.getInstance(element.getProject()); if (model.getState().isValidateCSSClasses()) { final RandoriProject compiler = RandoriCompilerSession.getLastCompiler(); if (compiler != null) { String className = txt.substring(1, txt.length() - 1); IASProjectAccess projectAccess = compiler.getProjectAccess(); if (projectAccess != null) { result = (projectAccess.getType(className) != null); } } } } } return result; } @Override public boolean isMultiValueProperty() { return true; } @Override public boolean isShorthandValue() { return false; } @NotNull @Override public String[] expand(@NotNull CssDeclaration declaration) { return new String[0]; } @Nullable @Override public PsiElement[] getShorthandPsiValue(@NotNull CssDeclaration decl, @NotNull String propertyName) { return new PsiElement[0]; } @Override public boolean is4ValueProperty() { return true; } @Override public CssPropertyValue getReferencedPropertyValue(@NotNull String name) { return null; } @NotNull @Override public CssPropertyInfo[] getInfos() { return new CssPropertyInfo[0]; } @NotNull @Override public String getPropertyName() { return _propertyName; } @Override public boolean allowsLengthes() { return false; } @Override public boolean allowsPercentages() { return false; } @Override public boolean hasStringValue() { return true; } @Override public Object[] getAllVariants() { return new Object[0]; } @Nullable @Override public String[] getRefNames() { return new String[0]; } @NotNull @Override public Object[] getVariants(@NotNull PsiElement contextElement) { if (!_propertyName.equals("-randori-fragment")) { return getSubClassesForPropertyName(_propertyName, contextElement.getProject()); } else { return getHTMLFilesInProject(contextElement.getProject()); } } private Object[] getHTMLFilesInProject(@NotNull Project project) { VirtualFile baseDir = project.getBaseDir(); Collection<String> HTMLFiles = new ArrayList<String>(); getHTMLFilesInDirectory(baseDir, HTMLFiles); Object[] result = new Object[HTMLFiles.size()]; int i = 0; String baseDirString = baseDir.getPath(); for (String HTMLFile : HTMLFiles) { HTMLFile = HTMLFile.substring(baseDirString.length()); result[i++] = LookupElementBuilder.create("\"" + HTMLFile + "\"").withPresentableText(HTMLFile); } return result; } private void getHTMLFilesInDirectory(VirtualFile directory, Collection<String> htmlFiles) { VirtualFile[] children = directory.getChildren(); for (VirtualFile file : children) { if (!file.isDirectory()) { String extension = file.getExtension(); if (extension != null && extension.equals(HTML_EXT) || extension.equals(HTM_EXT)) { htmlFiles.add(file.getPath()); } } else { getHTMLFilesInDirectory(file, htmlFiles); } } } private Object[] getSubClassesForPropertyName(@NotNull String propertyName, @NotNull Project project) { String superClass = getSuperClassNameForCSSDeclaration(propertyName); if (superClass != null) { final RandoriProject compiler = RandoriCompilerSession.getLastCompiler(); if (compiler != null) { IASProjectAccess projectAccess = compiler.getProjectAccess(); if (projectAccess != null) { Collection<IClassDefinition> subClasses = getSubClasses(superClass, projectAccess); if (subClasses != null) { Object[] result = new Object[subClasses.size()]; int i = 0; for (IClassDefinition definition : subClasses) { result[i++] = LookupElementBuilder.create("\"" + definition.getQualifiedName() + "\"") .withPresentableText(definition.getQualifiedName()); } return result; } } } } return null; } 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); } return null; } @Override public boolean getInherited() { return false; } @NotNull @Override public String toCannonicalName(@NotNull String propertyName) { return propertyName; } @Override public CssPropertyValue getValue() { return null; } @NotNull @Override public PsiElement[] getDeclarations(PsiElement context) { return new PsiElement[0]; } @Override public boolean allowsIntegerWithoutSuffix() { return false; } }