mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-86368 Groovy: Create From Usage: Code Completion for destination package is missing in Create Class/Interface/Enum dialog
This commit is contained in:
@@ -124,6 +124,7 @@ import.class=Import Class
|
||||
create.class.family.name=Create Class
|
||||
create.class.text=Create Class {0}
|
||||
create.interface.text=Create Interface {0}
|
||||
create.annotation.text=Create Annotation {0}
|
||||
static.declaration.in.inner.class=Inner classes cannot have static declarations
|
||||
constructors.are.not.allowed.in.anonymous.class=Constructors are not allowed in anonymous class
|
||||
no.such.property=Property ''{0}'' does not exist
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodBodyFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateConstructorMatchingSuperFix;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementUtil;
|
||||
@@ -1981,21 +1982,29 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
|
||||
}
|
||||
else {
|
||||
if (shouldBeInterface(refElement)) {
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.INTERFACE));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE));
|
||||
}
|
||||
else if (shouldBeClass(refElement)) {
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.CLASS));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.ENUM));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM));
|
||||
}
|
||||
else if (shouldBeAnnotation(refElement)) {
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION));
|
||||
}
|
||||
else {
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.CLASS));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.INTERFACE));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassActionBase.Type.ENUM));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM));
|
||||
annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldBeAnnotation(GrReferenceElement element) {
|
||||
return element.getParent() instanceof GrAnnotation;
|
||||
}
|
||||
|
||||
private static boolean shouldBeInterface(GrReferenceElement myRefElement) {
|
||||
PsiElement parent = myRefElement.getParent();
|
||||
return parent instanceof GrImplementsClause || parent instanceof GrExtendsClause && parent.getParent() instanceof GrInterfaceDefinition;
|
||||
|
||||
+22
-6
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.annotator.intentions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.impl.CreateClassDialog;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
@@ -24,7 +26,9 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
@@ -40,12 +44,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
|
||||
* @author ilyas
|
||||
*/
|
||||
public abstract class CreateClassActionBase implements IntentionAction {
|
||||
private Type myType;
|
||||
private CreateClassKind myType;
|
||||
|
||||
protected final GrReferenceElement myRefElement;
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.annotator.intentions.CreateClassActionBase");
|
||||
|
||||
public CreateClassActionBase(Type type, GrReferenceElement refElement) {
|
||||
public CreateClassActionBase(CreateClassKind type, GrReferenceElement refElement) {
|
||||
myType = type;
|
||||
myRefElement = refElement;
|
||||
}
|
||||
@@ -60,6 +64,8 @@ public abstract class CreateClassActionBase implements IntentionAction {
|
||||
return GroovyBundle.message("create.class.text", referenceName);
|
||||
case INTERFACE:
|
||||
return GroovyBundle.message("create.interface.text", referenceName);
|
||||
case ANNOTATION:
|
||||
return GroovyBundle.message("create.annotation.text", referenceName);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -75,11 +81,11 @@ public abstract class CreateClassActionBase implements IntentionAction {
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected Type getType() {
|
||||
protected CreateClassKind getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
@@ -145,7 +151,17 @@ public abstract class CreateClassActionBase implements IntentionAction {
|
||||
}
|
||||
}
|
||||
|
||||
public static enum Type {
|
||||
ENUM, CLASS, INTERFACE
|
||||
@Nullable
|
||||
protected PsiDirectory getTargetDirectory(Project project, String qualifier, String name, Module module, String title) {
|
||||
CreateClassDialog dialog = new CreateClassDialog(project, title, name, qualifier, getType(), false, module) {
|
||||
@Override
|
||||
protected boolean reportBaseInSourceSelectionInTest() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
dialog.show();
|
||||
if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null;
|
||||
|
||||
return dialog.getTargetDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
+96
-62
@@ -16,12 +16,15 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.annotator.intentions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
@@ -34,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
@@ -49,58 +51,91 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
public abstract class CreateClassFix {
|
||||
|
||||
public static IntentionAction createClassFromNewAction(final GrNewExpression expression) {
|
||||
return new CreateClassActionBase(CreateClassActionBase.Type.CLASS, expression.getReferenceElement()) {
|
||||
return new CreateClassActionBase(CreateClassKind.CLASS, expression.getReferenceElement()) {
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
if (!(file instanceof GroovyFileBase)) return;
|
||||
GroovyFileBase groovyFile = (GroovyFileBase) file;
|
||||
final String qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : "";
|
||||
GroovyFileBase groovyFile = (GroovyFileBase)file;
|
||||
final PsiManager manager = myRefElement.getManager();
|
||||
final String name = myRefElement.getReferenceName();
|
||||
assert name != null;
|
||||
final Module module = ModuleUtil.findModuleForPsiElement(file);
|
||||
|
||||
final String qualifier;
|
||||
final String name;
|
||||
final Module module;
|
||||
final AccessToken accessToken = ReadAction.start();
|
||||
try {
|
||||
qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : "";
|
||||
name = myRefElement.getReferenceName();
|
||||
assert name != null;
|
||||
module = ModuleUtil.findModuleForPsiElement(file);
|
||||
}
|
||||
finally {
|
||||
accessToken.finish();
|
||||
}
|
||||
|
||||
PsiDirectory targetDirectory = getTargetDirectory(project, qualifier, name, module, getText());
|
||||
if (targetDirectory == null) return;
|
||||
|
||||
GrTypeDefinition targetClass = createClassByType(targetDirectory, name, manager, myRefElement, NewGroovyClassAction.GROOVY_CLASS);
|
||||
if (targetClass == null) return;
|
||||
|
||||
GrArgumentList argList = expression.getArgumentList();
|
||||
if (argList != null && argList.getNamedArguments().length + argList.getExpressionArguments().length > 0 && targetClass != null) {
|
||||
|
||||
PsiType[] argTypes = PsiUtil.getArgumentTypes(myRefElement, false);
|
||||
assert argTypes != null;
|
||||
|
||||
ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length];
|
||||
String[] paramTypes = new String[argTypes.length];
|
||||
String[] paramNames = new String[argTypes.length];
|
||||
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
PsiType argType = argTypes[i];
|
||||
if (argType == null) argType = TypesUtil.getJavaLangObject(myRefElement);
|
||||
paramTypes[i] = "Object";
|
||||
paramNames[i] = "o" + i;
|
||||
paramTypesExpressions[i] = new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, myRefElement.getManager());
|
||||
}
|
||||
|
||||
GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}");
|
||||
method = targetClass.addMemberDeclaration(method, null);
|
||||
final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(myRefElement, PsiMethod.class, PsiClass.class);
|
||||
IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context);
|
||||
} else {
|
||||
PsiType[] argTypes = getArgTypes(myRefElement);
|
||||
if (argTypes != null) {
|
||||
generateConstructor(myRefElement, name, argTypes, targetClass, project);
|
||||
}
|
||||
else {
|
||||
putCursor(project, targetClass.getContainingFile(), targetClass);
|
||||
}
|
||||
addImportForClass(groovyFile, qualifier, targetClass);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public static IntentionAction createClassFixAction(final GrReferenceElement refElement, CreateClassActionBase.Type type) {
|
||||
return new CreateClassActionBase(type, refElement) {
|
||||
@Nullable
|
||||
private static PsiType[] getArgTypes(GrReferenceElement refElement) {
|
||||
final AccessToken accessToken = ReadAction.start();
|
||||
try {
|
||||
return PsiUtil.getArgumentTypes(refElement, false);
|
||||
}
|
||||
finally {
|
||||
accessToken.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateConstructor(@NotNull PsiElement refElement,
|
||||
@NotNull String name,
|
||||
@NotNull PsiType[] argTypes,
|
||||
@NotNull GrTypeDefinition targetClass,
|
||||
@NotNull Project project) {
|
||||
final AccessToken writeLock = WriteAction.start();
|
||||
try {
|
||||
ChooseTypeExpression[] paramTypesExpressions = new ChooseTypeExpression[argTypes.length];
|
||||
String[] paramTypes = new String[argTypes.length];
|
||||
String[] paramNames = new String[argTypes.length];
|
||||
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
PsiType argType = argTypes[i];
|
||||
if (argType == null) argType = TypesUtil.getJavaLangObject(refElement);
|
||||
paramTypes[i] = "Object";
|
||||
paramNames[i] = "o" + i;
|
||||
paramTypesExpressions[i] = new ChooseTypeExpression(new TypeConstraint[]{SupertypeConstraint.create(argType)}, refElement.getManager());
|
||||
}
|
||||
|
||||
GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}");
|
||||
|
||||
method = targetClass.addMemberDeclaration(method, null);
|
||||
final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(refElement, PsiMethod.class, PsiClass.class);
|
||||
IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context);
|
||||
}
|
||||
finally {
|
||||
writeLock.finish();
|
||||
}
|
||||
}
|
||||
|
||||
public static IntentionAction createClassFixAction(final GrReferenceElement refElement, CreateClassKind type) {
|
||||
return new CreateClassActionBase(type, refElement) {
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
if (!(file instanceof GroovyFileBase)) return;
|
||||
GroovyFileBase groovyFile = (GroovyFileBase) file;
|
||||
GroovyFileBase groovyFile = (GroovyFileBase)file;
|
||||
final String qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : "";
|
||||
final PsiManager manager = PsiManager.getInstance(project);
|
||||
final String name = myRefElement.getReferenceName();
|
||||
@@ -109,18 +144,7 @@ public abstract class CreateClassFix {
|
||||
if (targetDirectory == null) return;
|
||||
|
||||
|
||||
String templateName = null;
|
||||
switch (getType()) {
|
||||
case ENUM:
|
||||
templateName = NewGroovyClassAction.GROOVY_ENUM;
|
||||
break;
|
||||
case CLASS:
|
||||
templateName = NewGroovyClassAction.GROOVY_CLASS;
|
||||
break;
|
||||
case INTERFACE:
|
||||
templateName = NewGroovyClassAction.GROOVY_INTERFACE;
|
||||
break;
|
||||
}
|
||||
String templateName = getTemplateName(getType());
|
||||
assert name != null;
|
||||
PsiClass targetClass = createClassByType(targetDirectory, name, manager, myRefElement, templateName);
|
||||
if (targetClass != null) {
|
||||
@@ -128,29 +152,39 @@ public abstract class CreateClassFix {
|
||||
putCursor(project, targetClass.getContainingFile(), targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiDirectory getTargetDirectory(Project project, String qualifier, String name, Module module, String title) {
|
||||
GroovyCreateClassDialog dialog = new GroovyCreateClassDialog(project, title, name, qualifier, module);
|
||||
dialog.show();
|
||||
if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null;
|
||||
return dialog.getTargetDirectory();
|
||||
private static String getTemplateName(CreateClassKind createClassKind) {
|
||||
switch (createClassKind) {
|
||||
case ENUM:
|
||||
return NewGroovyClassAction.GROOVY_ENUM;
|
||||
case CLASS:
|
||||
return NewGroovyClassAction.GROOVY_CLASS;
|
||||
case INTERFACE:
|
||||
return NewGroovyClassAction.GROOVY_INTERFACE;
|
||||
case ANNOTATION:
|
||||
return NewGroovyClassAction.GROOVY_ANNOTATION;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static void addImportForClass(GroovyFileBase groovyFile, String qualifier, PsiClass targetClass) throws IncorrectOperationException {
|
||||
if (targetClass != null) {
|
||||
// add import for created class
|
||||
String qualifiedName = targetClass.getQualifiedName();
|
||||
if (qualifiedName != null && qualifiedName.contains(".")) {
|
||||
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
|
||||
if (!packageName.equals(qualifier)) {
|
||||
protected static void addImportForClass(@NotNull GroovyFileBase groovyFile, @NotNull String qualifier, @NotNull PsiClass targetClass)
|
||||
throws IncorrectOperationException {
|
||||
// add import for created class
|
||||
String qualifiedName = targetClass.getQualifiedName();
|
||||
if (qualifiedName != null && qualifiedName.contains(".")) {
|
||||
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
|
||||
if (!packageName.equals(qualifier)) {
|
||||
final AccessToken accessToken = WriteAction.start();
|
||||
try {
|
||||
groovyFile.addImportForClass(targetClass);
|
||||
}
|
||||
finally {
|
||||
accessToken.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user