package com.intellij.lang.javascript.flex; import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.javascript.flex.FlexAnnotationNames; import com.intellij.javascript.flex.mxml.FlexCommonTypeNames; import com.intellij.javascript.flex.resolve.ActionScriptClassResolver; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.flex.flexunit.FlexUnitSupport; import com.intellij.lang.javascript.flex.run.FlashRunConfigurationForm; import com.intellij.lang.javascript.flex.run.FlashRunConfigurationProducer; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.JSParameter; import com.intellij.lang.javascript.psi.JSVariable; import com.intellij.lang.javascript.psi.ecmal4.JSAttribute; import com.intellij.lang.javascript.psi.ecmal4.JSAttributeList; import com.intellij.lang.javascript.psi.ecmal4.JSAttributeListOwner; import com.intellij.lang.javascript.psi.ecmal4.JSClass; import com.intellij.lang.javascript.psi.resolve.JSImportHandlingUtil; import com.intellij.lang.javascript.psi.resolve.JSResolveUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.util.Processor; import org.jetbrains.annotations.NonNls; public class FlexImplicitUsageProvider implements ImplicitUsageProvider, Condition<PsiElement> { @Override public boolean isImplicitUsage(PsiElement element) { if (element instanceof XmlAttribute && ((XmlAttribute)element).isNamespaceDeclaration() && JavaScriptSupportLoader.isLanguageNamespace(((XmlAttribute)element).getValue())) { return true; } if (element instanceof JSClass) { JSClass clazz = (JSClass)element; final Module module = ModuleUtilCore.findModuleForPsiElement(clazz); if (module == null || ModuleType.get(module) != FlexModuleType.getInstance()) return false; if (FlashRunConfigurationProducer.isAcceptedMainClass(clazz, module)) return true; if (ActionScriptClassResolver.isParentClass(clazz, FlashRunConfigurationForm.MODULE_BASE_CLASS_NAME)) return true; FlexUnitSupport flexUnitSupport = FlexUnitSupport.getSupport(module); if (flexUnitSupport != null && flexUnitSupport.isTestClass(clazz, true)) return true; } else if (element instanceof JSFunction) { if (isTestMethod((JSFunction)element)) return true; if (isAnnotatedByUnknownAttribute((JSAttributeListOwner)element)) return true; } else if (element instanceof JSVariable) { if (isAnnotatedByUnknownAttribute((JSAttributeListOwner)element)) return true; if (JSResolveUtil.findParent(element) instanceof JSClass) { final JSAttributeList varAttrList = ((JSVariable)element).getAttributeList(); if (varAttrList != null && varAttrList.findAttributeByName(FlexAnnotationNames.EMBED) != null) { return true; } } } if (element instanceof JSParameter) { JSFunction function = PsiTreeUtil.getParentOfType(element, JSFunction.class); if (function != null) { final JSParameter[] params = function.getParameterVariables(); if (params.length == 1 && element == params[0]) { @NonNls String type = ((JSParameter)element).getTypeString(); if (type != null) type = JSImportHandlingUtil.resolveTypeName(type, element); if (type != null) { if (FlexCommonTypeNames.FLASH_EVENT_FQN.equals(type) || FlexCommonTypeNames.STARLING_EVENT_FQN.equals(type)) { return true; } boolean b = JSResolveUtil.processHierarchy(type, element.getContainingFile(), jsClass -> !FlexCommonTypeNames.FLASH_EVENT_FQN.equals(jsClass.getQualifiedName()) && !FlexCommonTypeNames.STARLING_EVENT_FQN.equals(jsClass.getQualifiedName()), false); if (!b) return true; } } } } return false; } private static boolean isTestMethod(JSFunction function) { Module moduleForPsiElement = ModuleUtilCore.findModuleForPsiElement(function); FlexUnitSupport flexUnitSupport = FlexUnitSupport.getSupport(moduleForPsiElement); if (flexUnitSupport != null && flexUnitSupport.isTestMethod(function)) return true; return false; } @Override public boolean isImplicitRead(PsiElement element) { return false; } @Override public boolean isImplicitWrite(PsiElement element) { return false; } // for "Can't be static" extension @Override public boolean value(PsiElement psiNamedElement) { if (psiNamedElement instanceof JSFunction) { if (isTestMethod((JSFunction)psiNamedElement)) return true; if (isAnnotatedByUnknownAttribute((JSAttributeListOwner)psiNamedElement)) return true; } return false; } private static boolean isAnnotatedByUnknownAttribute(JSAttributeListOwner namedElement) { JSAttributeList attributeList = namedElement.getAttributeList(); if (attributeList != null) { JSAttribute[] attributes = attributeList.getAttributes(); for (JSAttribute a : attributes) { if ("Deprecated".equals(a.getName())) continue; return true; } } return false; } }