mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
generate equals/hashCode: provide implicit variables for completion; show available variables as hint for CE users
This commit is contained in:
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.generation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -38,6 +39,13 @@ import java.util.*;
|
||||
*/
|
||||
public class GenerateEqualsHelper implements Runnable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateEqualsHelper");
|
||||
|
||||
@NonNls private static final String INSTANCE_NAME = "instanceBaseName";
|
||||
@NonNls private static final String BASE_PARAM_NAME = "baseParamName";
|
||||
@NonNls private static final String SUPER_HAS_EQUALS = "superHasEquals";
|
||||
@NonNls private static final String CHECK_PARAMETER_WITH_INSTANCEOF = "checkParameterWithInstanceof";
|
||||
@NonNls private static final String SUPER_HAS_HASH_CODE = "superHasHashCode";
|
||||
|
||||
private final PsiClass myClass;
|
||||
private final PsiField[] myEqualsFields;
|
||||
private final PsiField[] myHashCodeFields;
|
||||
@@ -141,7 +149,21 @@ public class GenerateEqualsHelper implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, PsiType> getEqualsImplicitVars(Project project) {
|
||||
final Map<String, PsiType> map = new LinkedHashMap<String, PsiType>();
|
||||
final PsiType stringType = project != null ? PsiType.getJavaLangString(PsiManager.getInstance(project), GlobalSearchScope.allScope(project))
|
||||
: PsiType.NULL;
|
||||
map.put(INSTANCE_NAME, stringType);
|
||||
map.put(BASE_PARAM_NAME, stringType);
|
||||
map.put(CHECK_PARAMETER_WITH_INSTANCEOF, PsiType.BOOLEAN);
|
||||
map.put(SUPER_HAS_EQUALS, PsiType.BOOLEAN);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static Map<String, PsiType> getHashCodeImplicitVars() {
|
||||
return ContainerUtil.newLinkedHashMap(Pair.create(SUPER_HAS_HASH_CODE, PsiType.BOOLEAN));
|
||||
}
|
||||
|
||||
private PsiMethod createEquals() throws IncorrectOperationException {
|
||||
@NonNls StringBuilder buffer = new StringBuilder();
|
||||
CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject);
|
||||
@@ -156,15 +178,15 @@ public class GenerateEqualsHelper implements Runnable {
|
||||
String[] nameSuggestions = codeStyleManager
|
||||
.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, classType).names;
|
||||
String instanceBaseName = nameSuggestions.length > 0 && nameSuggestions[0].length() < 10 ? nameSuggestions[0] : "that";
|
||||
contextMap.put("instanceName", instanceBaseName);
|
||||
contextMap.put(INSTANCE_NAME, instanceBaseName);
|
||||
|
||||
final PsiType objectType = PsiType.getJavaLangObject(myClass.getManager(), myClass.getResolveScope());
|
||||
nameSuggestions = codeStyleManager.suggestVariableName(VariableKind.PARAMETER, null, null, objectType).names;
|
||||
final String objectBaseName = nameSuggestions.length > 0 ? nameSuggestions[0] : "object";
|
||||
contextMap.put("baseParamName", objectBaseName);
|
||||
contextMap.put(BASE_PARAM_NAME, objectBaseName);
|
||||
final MethodSignature equalsSignature = getEqualsSignature(myProject, myClass.getResolveScope());
|
||||
contextMap.put("superHasEquals", superMethodExists(equalsSignature));
|
||||
contextMap.put("checkParameterWithInstanceof", myCheckParameterWithInstanceof);
|
||||
contextMap.put(SUPER_HAS_EQUALS, superMethodExists(equalsSignature));
|
||||
contextMap.put(CHECK_PARAMETER_WITH_INSTANCEOF, myCheckParameterWithInstanceof);
|
||||
|
||||
final String methodText = GenerationUtil
|
||||
.velocityGenerateCode(myClass, equalsFields, myNonNullSet, new HashMap<String, String>(), contextMap,
|
||||
@@ -203,7 +225,7 @@ public class GenerateEqualsHelper implements Runnable {
|
||||
@NonNls StringBuilder buffer = new StringBuilder();
|
||||
|
||||
final HashMap<String, Object> contextMap = new HashMap<String, Object>();
|
||||
contextMap.put("superHasHashCode", mySuperHasHashCode);
|
||||
contextMap.put(SUPER_HAS_HASH_CODE, mySuperHasHashCode);
|
||||
|
||||
final String methodText = GenerationUtil
|
||||
.velocityGenerateCode(myClass, Arrays.asList(myHashCodeFields), myNonNullSet, new HashMap<String, String>(), contextMap,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#set($classInstanceName = $helper.getUniqueLocalVarName($instanceName, $fields, $settings))
|
||||
#set($classInstanceName = $helper.getUniqueLocalVarName($instanceBaseName, $fields, $settings))
|
||||
#set($paramName = $helper.getUniqueLocalVarName($baseParamName, $fields, $settings))
|
||||
#macro(addClassInstance)
|
||||
#if ($settings.generateFinalLocals)
|
||||
|
||||
+3
-2
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight.generation.ui;
|
||||
|
||||
import com.intellij.codeInsight.generation.EqualsHashCodeTemplatesManager;
|
||||
import com.intellij.codeInsight.generation.GenerateEqualsHelper;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -135,8 +136,8 @@ public class EqualsHashCodeTemplatesPanel extends NamedItemsListEditor<Couple<Te
|
||||
|
||||
@Override
|
||||
protected UnnamedConfigurable createConfigurable(Couple<TemplateResource> item) {
|
||||
final GenerateTemplateConfigurable equalsConfigurable = new GenerateTemplateConfigurable(item.first, myProject);
|
||||
final GenerateTemplateConfigurable hashCodeConfigurable = new GenerateTemplateConfigurable(item.second, myProject);
|
||||
final GenerateTemplateConfigurable equalsConfigurable = new GenerateTemplateConfigurable(item.first, GenerateEqualsHelper.getEqualsImplicitVars(myProject), myProject);
|
||||
final GenerateTemplateConfigurable hashCodeConfigurable = new GenerateTemplateConfigurable(item.second, GenerateEqualsHelper.getHashCodeImplicitVars(), myProject);
|
||||
return new UnnamedConfigurable() {
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
+38
@@ -20,18 +20,29 @@
|
||||
package org.jetbrains.java.generate.template;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.java.generate.element.FieldElement;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class TemplatesManager implements PersistentStateComponent<TemplatesState> {
|
||||
|
||||
public static final Key<Map<String, PsiType>> TEMPLATE_IMPLICITS = Key.create("TEMPLATE_IMPLICITS");
|
||||
|
||||
private TemplatesState myState = new TemplatesState();
|
||||
|
||||
public abstract TemplateResource[] getDefaultTemplates();
|
||||
@@ -104,4 +115,31 @@ public abstract class TemplatesManager implements PersistentStateComponent<Templ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiType createFieldListElementType(Project project) {
|
||||
final PsiType classType = createElementType(project, FieldElement.class);
|
||||
final PsiClass listClass = JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_UTIL_LIST, GlobalSearchScope.allScope(project));
|
||||
return listClass != null ? JavaPsiFacade.getElementFactory(project).createType(listClass, classType) : PsiType.NULL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiType createElementType(Project project, Class<?> elementClass) {
|
||||
final List<String> methodNames =
|
||||
ContainerUtil.mapNotNull(elementClass.getMethods(),
|
||||
new Function<Method, String>() {
|
||||
@Override
|
||||
public String fun(Method method) {
|
||||
final String methodName = method.getName();
|
||||
if (methodName.startsWith("set")) {
|
||||
//hide setters from completion list
|
||||
return null;
|
||||
}
|
||||
return method.getGenericReturnType().getTypeName() + " " + methodName + "();";
|
||||
}
|
||||
});
|
||||
final String text = "interface " + elementClass.getSimpleName() + " {\n" + StringUtil.join(methodNames, "\n") + "}";
|
||||
final PsiClass aClass = JavaPsiFacade.getElementFactory(project).createClassFromText(text, null).getInnerClasses()[0];
|
||||
return JavaPsiFacade.getElementFactory(project).createType(aClass);
|
||||
}
|
||||
}
|
||||
+31
-2
@@ -30,20 +30,33 @@ import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ex.MultiLineLabel;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import org.jetbrains.java.generate.element.ClassElement;
|
||||
import org.jetbrains.java.generate.template.TemplateResource;
|
||||
import org.jetbrains.java.generate.template.TemplatesManager;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class GenerateTemplateConfigurable implements UnnamedConfigurable{
|
||||
private final TemplateResource template;
|
||||
private final Editor myEditor;
|
||||
private final List<String> availableImplicits = new ArrayList<String>();
|
||||
|
||||
public GenerateTemplateConfigurable(TemplateResource template, Project project) {
|
||||
public GenerateTemplateConfigurable(TemplateResource template, Project project) {
|
||||
this(template, Collections.<String, PsiType>emptyMap(), project);
|
||||
}
|
||||
|
||||
public GenerateTemplateConfigurable(TemplateResource template, Map<String, PsiType> contextMap, Project project) {
|
||||
this.template = template;
|
||||
final EditorFactory factory = EditorFactory.getInstance();
|
||||
Document doc = factory.createDocument(template.getTemplate());
|
||||
@@ -51,6 +64,15 @@ public class GenerateTemplateConfigurable implements UnnamedConfigurable{
|
||||
if (project != null && ftl != null) {
|
||||
final PsiFile file = PsiFileFactory.getInstance(project)
|
||||
.createFileFromText(template.getFileName(), ftl, template.getTemplate(), LocalTimeCounter.currentTime(), true);
|
||||
if (!template.isDefault()) {
|
||||
final HashMap<String, PsiType> map = new LinkedHashMap<String, PsiType>();
|
||||
map.put("java_version", PsiType.INT);
|
||||
map.put("class", TemplatesManager.createElementType(project, ClassElement.class));
|
||||
map.put("fields", TemplatesManager.createFieldListElementType(project));
|
||||
map.putAll(contextMap);
|
||||
availableImplicits.addAll(map.keySet());
|
||||
file.getViewProvider().putUserData(TemplatesManager.TEMPLATE_IMPLICITS, map);
|
||||
}
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
if (document != null) {
|
||||
doc = document;
|
||||
@@ -60,7 +82,14 @@ public class GenerateTemplateConfigurable implements UnnamedConfigurable{
|
||||
}
|
||||
|
||||
public JComponent createComponent() {
|
||||
return myEditor.getComponent();
|
||||
final JComponent component = myEditor.getComponent();
|
||||
if (availableImplicits.isEmpty()) {
|
||||
return component;
|
||||
}
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(component, BorderLayout.CENTER);
|
||||
panel.add(new MultiLineLabel("Available implicit variables:\n" + StringUtil.join(availableImplicits, ", ")), BorderLayout.SOUTH);
|
||||
return panel;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
|
||||
Reference in New Issue
Block a user