From b8153ebd95199d6f62ef830327bc5c3a26f606b9 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Thu, 24 Aug 2017 20:14:59 +0300 Subject: [PATCH] [jvm-lang] render Create Field requests in Java sources --- .../quickfix/CreateFieldFromUsageFix.java | 8 +- .../impl/quickfix/CreateFromUsageBaseFix.java | 10 +- .../impl/quickfix/CreateFromUsageUtils.java | 2 +- .../JavaCreateFieldFromUsageHelper.java | 4 +- .../impl/JavaElementActionsFactory.kt | 12 ++ .../java/actions/CreateEnumConstantAction.kt | 100 ++++++++++++ .../lang/java/actions/CreateFieldAction.kt | 145 ++++++++++++++++++ .../java/actions/CreateFieldActionBase.kt | 35 +++++ .../lang/java/actions/Workaround.java | 28 ++++ .../intellij/lang/java/actions/jvmPsiUtil.kt | 56 +++++++ .../src/messages/QuickFixBundle.properties | 2 + 11 files changed, 390 insertions(+), 12 deletions(-) create mode 100644 java/java-impl/src/com/intellij/lang/java/actions/CreateEnumConstantAction.kt create mode 100644 java/java-impl/src/com/intellij/lang/java/actions/CreateFieldAction.kt create mode 100644 java/java-impl/src/com/intellij/lang/java/actions/CreateFieldActionBase.kt create mode 100644 java/java-impl/src/com/intellij/lang/java/actions/Workaround.java create mode 100644 java/java-impl/src/com/intellij/lang/java/actions/jvmPsiUtil.kt 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 0f811d1bde53..2f87f6b9aaad 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -112,7 +112,7 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { public static void createFieldFromUsageTemplate(final PsiClass targetClass, final Project project, - final ExpectedTypeInfo[] expectedTypes, + final Object expectedTypes, final PsiField field, final boolean createConstantField, final PsiElement context) { @@ -138,11 +138,11 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { }); } - private static boolean shouldCreateFinalMember(@NotNull PsiReferenceExpression ref, @NotNull PsiClass targetClass) { + public static boolean shouldCreateFinalMember(@NotNull PsiReferenceExpression ref, @NotNull PsiClass targetClass) { if (!PsiTreeUtil.isAncestor(targetClass, ref, true)) { return false; } - final PsiElement element = PsiTreeUtil.getParentOfType(ref, PsiClassInitializer.class, PsiMethod.class); + final PsiElement element = PsiTreeUtil.getParentOfType(ref, PsiClassInitializer.class, PsiMethod.class, PsiField.class); if (element instanceof PsiClassInitializer) { return true; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java index 5e71a9edc968..142bf3ebce8c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -153,7 +153,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction { } @Nullable("null means unable to open the editor") - protected static Editor positionCursor(@NotNull Project project, @NotNull PsiFile targetFile, @NotNull PsiElement element) { + public static Editor positionCursor(@NotNull Project project, @NotNull PsiFile targetFile, @NotNull PsiElement element) { TextRange range = element.getTextRange(); LOG.assertTrue(range != null, element.getClass()); int textOffset = range.getStartOffset(); @@ -193,7 +193,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction { } } - protected static boolean shouldCreateStaticMember(PsiReferenceExpression ref, PsiClass targetClass) { + public static boolean shouldCreateStaticMember(PsiReferenceExpression ref, PsiClass targetClass) { PsiExpression qualifierExpression = ref.getQualifierExpression(); while (qualifierExpression instanceof PsiParenthesizedExpression) { @@ -253,7 +253,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction { return null; } - protected static PsiSubstitutor getTargetSubstitutor (PsiElement element) { + public static PsiSubstitutor getTargetSubstitutor (PsiElement element) { if (element instanceof PsiNewExpression) { JavaResolveResult result = ((PsiNewExpression)element).getClassOrAnonymousClassReference().advancedResolve(false); PsiSubstitutor substitutor = result.getSubstitutor(); @@ -408,7 +408,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction { return psiClass.getManager().isInProject(psiClass); } - protected static void startTemplate (@NotNull Editor editor, final Template template, @NotNull final Project project) { + public static void startTemplate (@NotNull Editor editor, final Template template, @NotNull final Project project) { startTemplate(editor, template, project, null); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java index 9e7cf1ad5dba..c72f265b9790 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java @@ -658,7 +658,7 @@ public class CreateFromUsageUtils { } @NotNull - static ExpectedTypeInfo[] guessExpectedTypes(@NotNull PsiExpression expression, boolean allowVoidType) { + public static ExpectedTypeInfo[] guessExpectedTypes(@NotNull PsiExpression expression, boolean allowVoidType) { PsiManager manager = expression.getManager(); GlobalSearchScope resolveScope = expression.getResolveScope(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java index f5a0da4b9cf8..24e1fc2d1472 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -72,7 +72,7 @@ public class JavaCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper { } @Override - public PsiField insertFieldImpl(@NotNull PsiClass targetClass, @NotNull PsiField field, @NotNull PsiElement place) { + public PsiField insertFieldImpl(@NotNull PsiClass targetClass, @NotNull PsiField field, @Nullable PsiElement place) { PsiMember enclosingContext = null; PsiClass parentClass; do { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/JavaElementActionsFactory.kt b/java/java-impl/src/com/intellij/codeInsight/intention/impl/JavaElementActionsFactory.kt index bda6f283c304..7bf2780c6858 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/JavaElementActionsFactory.kt +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/JavaElementActionsFactory.kt @@ -20,7 +20,11 @@ import com.intellij.codeInsight.daemon.impl.quickfix.AddConstructorFix import com.intellij.codeInsight.daemon.impl.quickfix.ModifierFix import com.intellij.codeInsight.intention.AbstractIntentionAction import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.lang.java.actions.CreateEnumConstantAction +import com.intellij.lang.java.actions.CreateFieldAction +import com.intellij.lang.java.actions.toJavaClassOrNull import com.intellij.lang.jvm.* +import com.intellij.lang.jvm.actions.CreateFieldRequest import com.intellij.lang.jvm.actions.JvmElementActionsFactory import com.intellij.lang.jvm.actions.MemberRequest import com.intellij.lang.jvm.types.JvmType @@ -124,6 +128,14 @@ class JavaElementActionsFactory( } } + override fun createAddFieldActions(targetClass: JvmClass, request: CreateFieldRequest): List { + val javaClass = targetClass.toJavaClassOrNull() ?: return emptyList() + return listOf( + CreateFieldAction(javaClass, request, false), + CreateFieldAction(javaClass, request, true), + CreateEnumConstantAction(javaClass, request) + ) + } } class JavaElementRenderer { diff --git a/java/java-impl/src/com/intellij/lang/java/actions/CreateEnumConstantAction.kt b/java/java-impl/src/com/intellij/lang/java/actions/CreateEnumConstantAction.kt new file mode 100644 index 000000000000..5fda39355967 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/actions/CreateEnumConstantAction.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2000-2017 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 com.intellij.lang.java.actions + +import com.intellij.codeInsight.CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement +import com.intellij.codeInsight.ExpectedTypeUtil +import com.intellij.codeInsight.daemon.QuickFixBundle +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageBaseFix.positionCursor +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageBaseFix.startTemplate +import com.intellij.codeInsight.daemon.impl.quickfix.EmptyExpression +import com.intellij.codeInsight.template.TemplateBuilderImpl +import com.intellij.lang.java.actions.Workaround.extractExpectedTypes +import com.intellij.lang.jvm.actions.CreateFieldRequest +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiEnumConstant +import com.intellij.psi.PsiFile + +class CreateEnumConstantAction(targetClass: PsiClass, request: CreateFieldRequest) : CreateFieldActionBase(targetClass, request) { + + private val myData: EnumConstantData? + get() { + val targetClass = myTargetClass.element + if (targetClass == null || !request.isValid) return null + return extractRenderData(targetClass, request) + } + + override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean { + val data = myData ?: return false + text = QuickFixBundle.message("create.enum.constant.from.usage.text", data.constantName) + return true + } + + override fun invoke(project: Project, editor: Editor?, file: PsiFile?) { + val data = myData ?: return + val name = data.constantName + val targetClass = data.targetClass + val elementFactory = JavaPsiFacade.getElementFactory(project)!! + + // add constant + var enumConstant: PsiEnumConstant + enumConstant = elementFactory.createEnumConstantFromText(name, null) + enumConstant = targetClass.add(enumConstant) as PsiEnumConstant + + // start template + val constructor = targetClass.constructors.firstOrNull() ?: return + val parameters = constructor.parameterList.parameters + if (parameters.isEmpty()) return + + val paramString = parameters.joinToString(",") { it.name ?: "" } + enumConstant = enumConstant.replace(elementFactory.createEnumConstantFromText("$name($paramString)", null)) as PsiEnumConstant + + val builder = TemplateBuilderImpl(enumConstant) + val argumentList = enumConstant.argumentList!! + for (expression in argumentList.expressions) { + builder.replaceElement(expression, EmptyExpression()) + } + enumConstant = forcePsiPostprocessAndRestoreElement(enumConstant) + val template = builder.buildTemplate() + + val newEditor = positionCursor(project, targetClass.containingFile, enumConstant) ?: return + val range = enumConstant.textRange + newEditor.document.deleteString(range.startOffset, range.endOffset) + startTemplate(newEditor, template, project) + } +} + +private class EnumConstantData( + val targetClass: PsiClass, + val constantName: String +) + +private fun extractRenderData(targetClass: PsiClass, request: CreateFieldRequest): EnumConstantData? { + if (!targetClass.isEnum) return null + if (!checkExpectedTypes(request.fieldType, targetClass, targetClass.project)) return null + return EnumConstantData(targetClass, request.fieldName) +} + +private fun checkExpectedTypes(types: Any?, targetClass: PsiClass, project: Project): Boolean { + val typeInfos = extractExpectedTypes(types) ?: return true + val enumType = JavaPsiFacade.getElementFactory(project).createType(targetClass) + return typeInfos.any { + ExpectedTypeUtil.matches(enumType, it) + } +} diff --git a/java/java-impl/src/com/intellij/lang/java/actions/CreateFieldAction.kt b/java/java-impl/src/com/intellij/lang/java/actions/CreateFieldAction.kt new file mode 100644 index 000000000000..05486e36167b --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/actions/CreateFieldAction.kt @@ -0,0 +1,145 @@ +/* + * Copyright 2000-2017 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 com.intellij.lang.java.actions + +import com.intellij.codeInsight.daemon.QuickFixBundle.message +import com.intellij.codeInsight.daemon.impl.quickfix.CreateFieldFromUsageFix +import com.intellij.codeInsight.daemon.impl.quickfix.JavaCreateFieldFromUsageHelper +import com.intellij.lang.java.request.CreateFieldFromJavaUsageRequest +import com.intellij.lang.jvm.JvmModifier +import com.intellij.lang.jvm.actions.CreateFieldRequest +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.* +import com.intellij.psi.presentation.java.ClassPresentationUtil.getNameForClass +import com.intellij.psi.util.PsiUtil + +internal class CreateFieldAction( + targetClass: PsiClass, + request: CreateFieldRequest, + private val constantField: Boolean +) : CreateFieldActionBase(targetClass, request) { + + private val myData: FieldData? + get() { + val targetClass = myTargetClass.element + if (targetClass == null || !request.isValid) return null + return extractRenderData(targetClass, request, constantField) + } + + override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?): Boolean { + val data = myData ?: return false + val className = getNameForClass(data.targetClass, false) + text = if (constantField) { + message("create.constant.from.usage.full.text", data.fieldName, className) + } + else { + message("create.field.from.usage.full.text", data.fieldName, className) + } + return true + } + + override fun invoke(project: Project, editor: Editor?, file: PsiFile?) { + val data = myData ?: return + val targetClass = data.targetClass + + // render template field + val renderedField = JavaPsiFacade.getElementFactory(project).createField(data.fieldName, PsiType.INT) + + // clean template modifiers + renderedField.modifierList?.let { list -> + list.firstChild?.let { + list.deleteChildRange(it, list.lastChild) + } + } + // setup actual modifiers + for (modifier in data.modifiers) { + PsiUtil.setModifierProperty(renderedField, modifier, true) + } + + // insert field + val javaField = JavaCreateFieldFromUsageHelper().insertFieldImpl(targetClass, renderedField, data.anchor) + + // setup template + CreateFieldFromUsageFix.createFieldFromUsageTemplate( + targetClass, project, data.fieldType, javaField, data.constant, data.reference + ) + } +} + +private class FieldData( + val targetClass: PsiClass, + val fieldName: String, + val fieldType: Any?, + val reference: PsiReferenceExpression?, + val anchor: PsiElement?, + val modifiers: Collection, + val constant: Boolean +) + +private fun extractRenderData(targetClass: PsiClass, request: CreateFieldRequest, renderConstant: Boolean): FieldData? { + val fieldName = request.fieldName + val requestedModifiers = request.modifiers + + val canRender = run { + val constantRequested = request.constant || targetClass.isInterface || requestedModifiers.containsAll(constantModifiers) + if (renderConstant) { + constantRequested || fieldName.toUpperCase() == fieldName + } + else { + !constantRequested + } + } + if (!canRender) return null + + val modifiersToRender = if (renderConstant) { + if (targetClass.isInterface) { + // interface fields are public static final implicitly, so modifiers don't have to be rendered + requestedModifiers - constantModifiers - visibilityModifiers + } + else { + // render static final explicitly + requestedModifiers + constantModifiers + } + } + else { + // render as is + requestedModifiers + } + + val javaUsage = request as? CreateFieldFromJavaUsageRequest + return FieldData( + targetClass, + fieldName, + request.fieldType, + javaUsage?.reference, + javaUsage?.anchor, + modifiersToRender.map(JvmModifier::toPsi), + renderConstant + ) +} + +private val visibilityModifiers = setOf( + JvmModifier.PUBLIC, + JvmModifier.PROTECTED, + JvmModifier.PACKAGE_LOCAL, + JvmModifier.PRIVATE +) + +private val constantModifiers = setOf( + JvmModifier.STATIC, + JvmModifier.FINAL +) diff --git a/java/java-impl/src/com/intellij/lang/java/actions/CreateFieldActionBase.kt b/java/java-impl/src/com/intellij/lang/java/actions/CreateFieldActionBase.kt new file mode 100644 index 000000000000..c7fb806393c4 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/actions/CreateFieldActionBase.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2017 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 com.intellij.lang.java.actions + +import com.intellij.codeInsight.daemon.QuickFixBundle.message +import com.intellij.codeInsight.intention.impl.BaseIntentionAction +import com.intellij.lang.jvm.actions.CreateFieldRequest +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.util.createSmartPointer + +abstract class CreateFieldActionBase(targetClass: PsiClass, protected val request: CreateFieldRequest) : BaseIntentionAction() { + + protected val myTargetClass = targetClass.createSmartPointer() + + override fun getFamilyName(): String = message("create.field.from.usage.family") + + override fun getElementToMakeWritable(currentFile: PsiFile): PsiElement? = myTargetClass.element + + override fun startInWriteAction(): Boolean = true +} diff --git a/java/java-impl/src/com/intellij/lang/java/actions/Workaround.java b/java/java-impl/src/com/intellij/lang/java/actions/Workaround.java new file mode 100644 index 000000000000..5ad527ae287c --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/actions/Workaround.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2017 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 com.intellij.lang.java.actions; + +import com.intellij.codeInsight.ExpectedTypeInfo; +import org.jetbrains.annotations.Nullable; + +// workaround for KT-19388 +class Workaround { + + @Nullable + static ExpectedTypeInfo[] extractExpectedTypes(@Nullable Object types) { + return types instanceof ExpectedTypeInfo[] ? (ExpectedTypeInfo[])types : null; + } +} diff --git a/java/java-impl/src/com/intellij/lang/java/actions/jvmPsiUtil.kt b/java/java-impl/src/com/intellij/lang/java/actions/jvmPsiUtil.kt new file mode 100644 index 000000000000..83c42666da07 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/actions/jvmPsiUtil.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2017 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 com.intellij.lang.java.actions + +import com.intellij.lang.java.JavaLanguage +import com.intellij.lang.jvm.JvmClass +import com.intellij.lang.jvm.JvmModifier +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiModifier +import com.intellij.psi.PsiModifier.ModifierConstant +import com.intellij.psi.PsiTypeParameter +import com.intellij.psi.impl.compiled.ClsClassImpl + +@ModifierConstant +fun JvmModifier.toPsi(): String = when (this) { + JvmModifier.PUBLIC -> PsiModifier.PUBLIC + JvmModifier.PROTECTED -> PsiModifier.PROTECTED + JvmModifier.PRIVATE -> PsiModifier.PRIVATE + JvmModifier.PACKAGE_LOCAL -> PsiModifier.PACKAGE_LOCAL + JvmModifier.STATIC -> PsiModifier.STATIC + JvmModifier.ABSTRACT -> PsiModifier.ABSTRACT + JvmModifier.FINAL -> PsiModifier.FINAL + JvmModifier.DEFAULT -> PsiModifier.DEFAULT + JvmModifier.NATIVE -> PsiModifier.NATIVE + JvmModifier.SYNCHRONIZED -> PsiModifier.NATIVE + JvmModifier.STRICTFP -> PsiModifier.STRICTFP + JvmModifier.TRANSIENT -> PsiModifier.TRANSIENT + JvmModifier.VOLATILE -> PsiModifier.VOLATILE + JvmModifier.TRANSITIVE -> PsiModifier.TRANSITIVE +} + +/** + * Compiled classes, type parameters are not considered classes. + * + * @return Java PsiClass or `null` if the receiver is not a Java PsiClass + */ +fun JvmClass.toJavaClassOrNull(): PsiClass? { + if (this !is PsiClass) return null + if (this is PsiTypeParameter) return null + if (this is ClsClassImpl) return null + if (this.language != JavaLanguage.INSTANCE) return null + return this +} diff --git a/resources-en/src/messages/QuickFixBundle.properties b/resources-en/src/messages/QuickFixBundle.properties index 7b3cdfe76c80..7daa7e23c106 100644 --- a/resources-en/src/messages/QuickFixBundle.properties +++ b/resources-en/src/messages/QuickFixBundle.properties @@ -60,6 +60,7 @@ create.class.from.usage.text=Create {0} ''{1}'' create.inner.class.from.usage.text=Create inner {0} ''{1}'' create.constant.from.usage.family=Create Constant From Usage create.constant.from.usage.text=Create constant field ''{0}'' +create.constant.from.usage.full.text=Create constant field ''{0}'' in ''{1}'' create.enum.constant.from.usage.text=Create enum constant ''{0}'' create.constructor.from.new.family=Create Constructor from New create.constructor.from.new.text=Create constructor @@ -70,6 +71,7 @@ create.constructor.matching.super=Create constructor matching super super.class.constructors.chooser.title=Choose Super Class Constructors create.field.from.usage.family=Create field from Usage create.field.from.usage.text=Create field ''{0}'' +create.field.from.usage.full.text=Create field ''{0}'' in ''{1}'' target.class.chooser.title=Choose Target Class create.class.title=Create {0} create.enum=enum