blob: ca308cdcde6df45a67665b237b62c67812374c75 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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 org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodQuickFix;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.ArrayList;
import java.util.List;
/**
* User: anna
* Date: 1/16/13
*/
public class JavaFxEventHandlerReference extends PsiReferenceBase<XmlAttributeValue> {
private final PsiClass myCurrentTagClass;
private final PsiMethod myEventHandler;
private final PsiClass myController;
public JavaFxEventHandlerReference(XmlAttributeValue element, PsiClass currentTagClass, final PsiMethod method, PsiClass controller) {
super(element);
myCurrentTagClass = currentTagClass;
myEventHandler = method;
myController = controller;
}
@Nullable
@Override
public PsiElement resolve() {
return myEventHandler;
}
@NotNull
@Override
public Object[] getVariants() {
if (myController == null) return EMPTY_ARRAY;
final List<PsiMethod> availableHandlers = new ArrayList<PsiMethod>();
for (PsiMethod psiMethod : myController.getMethods()) {
if (isHandlerMethod(psiMethod)) {
availableHandlers.add(psiMethod);
}
}
return availableHandlers.isEmpty() ? EMPTY_ARRAY : ArrayUtil.toObjectArray(availableHandlers);
}
public static boolean isHandlerMethod(PsiMethod psiMethod) {
if (!psiMethod.hasModifierProperty(PsiModifier.STATIC) && PsiType.VOID.equals(psiMethod.getReturnType())) {
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
if (parameters.length == 1) {
final PsiType parameterType = parameters[0].getType();
if (InheritanceUtil.isInheritor(parameterType, JavaFxCommonClassNames.JAVAFX_EVENT)) {
return true;
}
}
return parameters.length == 0;
}
return false;
}
@Override
public TextRange getRangeInElement() {
final TextRange range = super.getRangeInElement();
return new TextRange(range.getStartOffset() + 1, range.getEndOffset());
}
public static class JavaFxUnresolvedReferenceHandlerQuickfixProvider extends UnresolvedReferenceQuickFixProvider<JavaFxEventHandlerReference> {
@Override
public void registerFixes(@NotNull final JavaFxEventHandlerReference ref, @NotNull final QuickFixActionRegistrar registrar) {
if (ref.myController != null && ref.myEventHandler == null) {
final CreateMethodQuickFix quickFix = CreateMethodQuickFix.createFix(ref.myController, getHandlerSignature(ref), "");
if (quickFix != null) {
registrar.register(quickFix);
}
}
}
private static String getHandlerSignature(JavaFxEventHandlerReference ref) {
final XmlAttributeValue element = ref.getElement();
String canonicalText = JavaFxCommonClassNames.JAVAFX_EVENT;
final PsiElement parent = element.getParent();
if (parent instanceof XmlAttribute) {
final XmlAttribute xmlAttribute = (XmlAttribute)parent;
final Project project = element.getProject();
final PsiField handlerField = ref.myCurrentTagClass.findFieldByName(xmlAttribute.getName(), true);
if (handlerField != null) {
final PsiClassType classType = JavaFxPsiUtil.getPropertyClassType(handlerField);
if (classType != null) {
final PsiClass eventHandlerClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_EVENT_EVENT_HANDLER, GlobalSearchScope.allScope(project));
final PsiTypeParameter[] typeParameters = eventHandlerClass != null ? eventHandlerClass.getTypeParameters() : null;
if (typeParameters != null && typeParameters.length == 1) {
final PsiTypeParameter typeParameter = typeParameters[0];
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(eventHandlerClass, classType);
final PsiType eventType = substitutor.substitute(typeParameter);
if (eventType != null) {
canonicalText = eventType.getCanonicalText();
}
}
}
}
}
return "public void " + element.getValue().substring(1) + "(" + canonicalText + " e)";
}
@NotNull
@Override
public Class<JavaFxEventHandlerReference> getReferenceClass() {
return JavaFxEventHandlerReference.class;
}
}
}