diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java index 18c2e0b1c6b4..139a605ae60d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java @@ -66,8 +66,6 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { } while (parentClass instanceof PsiAnonymousClass); - final PsiFile targetFile = targetClass.getContainingFile(); - ExpectedTypeInfo[] expectedTypes = CreateFromUsageUtils.guessExpectedTypes(myReferenceExpression, false); String fieldName = myReferenceExpression.getReferenceName(); @@ -94,10 +92,20 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { setupVisibility(parentClass, targetClass, field.getModifierList()); + createFieldFromUsageTemplate(targetClass, project, expectedTypes, field, createConstantField(), myReferenceExpression); + } + + public static void createFieldFromUsageTemplate(final PsiClass targetClass, + final Project project, + final ExpectedTypeInfo[] expectedTypes, + final PsiField field, + final boolean createConstantField, + final PsiElement context) { + final PsiFile targetFile = targetClass.getContainingFile(); final Editor newEditor = positionCursor(project, targetFile, field); if (newEditor == null) return; Template template = - CreateFieldFromUsageHelper.setupTemplate(field, expectedTypes, targetClass, newEditor, myReferenceExpression, createConstantField()); + CreateFieldFromUsageHelper.setupTemplate(field, expectedTypes, targetClass, newEditor, context, createConstantField); startTemplate(newEditor, template, project, new TemplateEditingAdapter() { @Override diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java index e7b7135d929b..7ac6b6972242 100644 --- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java +++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java @@ -40,6 +40,10 @@ public class JavaFXQuickfixTest extends DaemonAnalyzerTestCase { doTest("Create Method 'void bar(ActionEvent)'", true); } + public void testCreateField() throws Exception { + doTest("Create Field 'btn'", true); + } + private void doTest(final String actionName) throws Exception { doTest(actionName, false); } diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml index 76cd8a641f07..fc913b0d5deb 100644 --- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml +++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml @@ -9,6 +9,7 @@ + diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java index c649a37f8639..b4f8e47152af 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java @@ -15,28 +15,48 @@ */ package org.jetbrains.plugins.javaFX.fxml.refs; +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.ExpectedTypeInfoImpl; +import com.intellij.codeInsight.TailType; +import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageFix; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageHelper; +import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.ProcessingContext; +import com.intellij.util.VisibilityUtil; +import com.intellij.xml.XmlElementDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.javaFX.fxml.FxmlConstants; import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil; +import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor; import java.util.ArrayList; import java.util.List; /** -* User: anna -* Date: 1/17/13 -*/ + * User: anna + * Date: 1/17/13 + */ class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvider { @Override protected PsiReference[] getReferencesByElement(@NotNull final PsiClass aClass, final XmlAttributeValue xmlAttributeValue, ProcessingContext context) { final PsiField field = aClass.findFieldByName(xmlAttributeValue.getValue(), false); - return new PsiReference[] {new JavaFxControllerFieldRef(xmlAttributeValue, field, aClass)}; + return new PsiReference[]{new JavaFxControllerFieldRef(xmlAttributeValue, field, aClass)}; } public static class JavaFxControllerFieldRef extends PsiReferenceBase { @@ -54,7 +74,19 @@ class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvi @Nullable @Override public PsiElement resolve() { - return myField != null ? myField : myXmlAttributeValue; + if (myField != null) { + return myField; + } + else { + if (myAClass != null) { + final XmlFile xmlFile = (XmlFile)myXmlAttributeValue.getContainingFile(); + final XmlTag rootTag = xmlFile.getRootTag(); + if (rootTag != null && !FxmlConstants.FX_ROOT.equals(rootTag.getName())) { + return null; + } + } + return myXmlAttributeValue; + } } @NotNull @@ -72,4 +104,81 @@ class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvi return ArrayUtil.toObjectArray(fieldsToSuggest); } } + + public static class JavaFxUnresolvedReferenceHandlerQuickfixProvider extends UnresolvedReferenceQuickFixProvider { + @Override + public void registerFixes(final JavaFxControllerFieldRef ref, final QuickFixActionRegistrar registrar) { + if (ref.myAClass != null && ref.myField == null) { + final PsiClass fieldClass = CreateFieldFix.checkContext(ref.myXmlAttributeValue); + if (fieldClass != null) { + registrar.register(new CreateFieldFix(ref, fieldClass)); + } + } + } + + @NotNull + @Override + public Class getReferenceClass() { + return JavaFxControllerFieldRef.class; + } + + private static class CreateFieldFix extends PsiElementBaseIntentionAction { + private final PsiClass myFieldClass; + private final PsiClass myClass; + private final String myCanonicalText; + + public CreateFieldFix(JavaFxControllerFieldRef ref, PsiClass fieldClass) { + myFieldClass = fieldClass; + myClass = ref.myAClass; + myCanonicalText = ref.getCanonicalText(); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + + if (!CodeInsightUtilBase.prepareFileForWrite(myClass.getContainingFile())) { + return; + } + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + PsiField field = factory.createField(myCanonicalText, PsiType.INT); + VisibilityUtil.setVisibility(field.getModifierList(), PsiModifier.PUBLIC); + + field = CreateFieldFromUsageHelper.insertField(myClass, field, element); + + final PsiClassType fieldType = factory.createType(myFieldClass); + final ExpectedTypeInfo[] types = {new ExpectedTypeInfoImpl(fieldType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, 0, fieldType, TailType.NONE)}; + CreateFieldFromUsageFix.createFieldFromUsageTemplate(myClass, project, types, field, false, element); + } + + protected static PsiClass checkContext(final XmlAttributeValue attributeValue) { + if (attributeValue == null) return null; + final PsiElement parent = attributeValue.getParent(); + if (parent instanceof XmlAttribute){ + final XmlTag tag = ((XmlAttribute)parent).getParent(); + if (tag != null) { + final XmlElementDescriptor descriptor = tag.getDescriptor(); + if (descriptor instanceof JavaFxClassBackedElementDescriptor) { + final PsiElement declaration = descriptor.getDeclaration(); + if (declaration instanceof PsiClass) { + return (PsiClass)declaration; + } + } + } + } + return null; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + setText(QuickFixBundle.message("create.field.from.usage.text", myCanonicalText)); + return element.isValid(); + } + + @NotNull + @Override + public String getFamilyName() { + return QuickFixBundle.message("create.field.from.usage.family"); + } + } + } } diff --git a/plugins/javaFX/testData/quickfix/CreateField.java b/plugins/javaFX/testData/quickfix/CreateField.java new file mode 100644 index 000000000000..e72dc651892b --- /dev/null +++ b/plugins/javaFX/testData/quickfix/CreateField.java @@ -0,0 +1 @@ +public class CreateControllerMethod {} \ No newline at end of file diff --git a/plugins/javaFX/testData/quickfix/CreateField_after.java b/plugins/javaFX/testData/quickfix/CreateField_after.java new file mode 100644 index 000000000000..a247a27be877 --- /dev/null +++ b/plugins/javaFX/testData/quickfix/CreateField_after.java @@ -0,0 +1,5 @@ +import javafx.scene.control.Button; + +public class CreateControllerMethod { + public Button btn; +} \ No newline at end of file diff --git a/plugins/javaFX/testData/quickfix/createField.fxml b/plugins/javaFX/testData/quickfix/createField.fxml new file mode 100644 index 000000000000..a4f21c4d63a5 --- /dev/null +++ b/plugins/javaFX/testData/quickfix/createField.fxml @@ -0,0 +1,5 @@ + + + +