Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code generator record and enum updates. #7339

Merged
merged 1 commit into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.sun.source.util.Trees;
import java.io.IOException;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import javax.lang.model.element.Element;
Expand Down Expand Up @@ -92,10 +93,12 @@ public AddPropertyCodeGenerator(JTextComponent component, String className, List
this.vcsName = vcsName;
}

@Override
public String getDisplayName() {
return NbBundle.getMessage(AddPropertyCodeGenerator.class, "DN_AddProperty");
}

@Override
public void invoke() {
Object o = component.getDocument().getProperty(Document.StreamDescriptionProperty);

Expand Down Expand Up @@ -216,6 +219,7 @@ public void run(CompilationController parameter) throws Exception {
r.lock();
try {
NbDocument.runAtomicAsUser((StyledDocument) doc, new Runnable() {
@Override
public void run() {
try {
GuardedSectionManager manager = GuardedSectionManager.getInstance((StyledDocument) doc);
Expand Down Expand Up @@ -256,6 +260,7 @@ public void run() {
// code insertion to document passed
try {
JavaSource.forFileObject(file).runModificationTask(new Task<WorkingCopy>() {
@Override
public void run(WorkingCopy workingCopy) throws Exception {
workingCopy.toPhase(Phase.RESOLVED);

Expand Down Expand Up @@ -352,11 +357,17 @@ public Void visitClass(ClassTree node, Void p) {

public static final class Factory implements CodeGenerator.Factory {

private static final EnumSet<Tree.Kind> TREE_KINDS = EnumSet.copyOf(TreeUtilities.CLASS_TREE_KINDS);
static {
TREE_KINDS.remove(Tree.Kind.RECORD); // no fields in records
}

@Override
public List<? extends CodeGenerator> create(Lookup context) {
JTextComponent component = context.lookup(JTextComponent.class);
CompilationController cc = context.lookup(CompilationController.class);
TreePath path = context.lookup(TreePath.class);
while (path != null && !TreeUtilities.CLASS_TREE_KINDS.contains(path.getLeaf().getKind())) {
while (path != null && !TREE_KINDS.contains(path.getLeaf().getKind())) {
path = path.getParentPath();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.swing.text.JTextComponent;
import org.netbeans.api.java.source.Task;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.ElementHandle;
import org.netbeans.api.java.source.ElementUtilities;
import org.netbeans.api.java.source.GeneratorUtilities;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.ModificationResult;
Expand All @@ -95,6 +97,7 @@
public class EqualsHashCodeGenerator implements CodeGenerator {

private static final String ERROR = "<error>"; //NOI18N
private static final Set<ElementKind> TREE_KINDS = EnumSet.of(ElementKind.CLASS, ElementKind.RECORD);

public static class Factory implements CodeGenerator.Factory {

Expand Down Expand Up @@ -152,7 +155,7 @@ public String getDisplayName() {
}

static EqualsHashCodeGenerator createEqualsHashCodeGenerator(JTextComponent component, CompilationController cc, Element el) throws IOException {
if (el.getKind() != ElementKind.CLASS) {
if (!TREE_KINDS.contains(el.getKind())) {
return null;
}
//#125114: ignore anonymous innerclasses:
Expand Down Expand Up @@ -203,12 +206,15 @@ public Void visitMemberSelect(MemberSelectTree sel, VariableElement what) {
return super.visitMemberSelect(sel, what);
}
}
Trees tree = cc.getTrees();
for (ExecutableElement e : methods) {
if (e == null) {
continue;
}
Trees tree = cc.getTrees();
TreePath path = tree.getPath(e);
if (path == null) {
continue;
}
Used used = new Used();
used.scan(path, field);
if (used.found) {
Expand All @@ -232,7 +238,7 @@ public static ExecutableElement[] overridesHashCodeAndEquals(CompilationInfo com
if (el == null) {
return ret;
}
if (type == null || type.getKind() != ElementKind.CLASS) {
if (type == null || !TREE_KINDS.contains(type.getKind())) {
return ret;
}

Expand Down Expand Up @@ -266,6 +272,8 @@ public static ExecutableElement[] overridesHashCodeAndEquals(CompilationInfo com
return ret;
}

Elements elements = compilationInfo.getElements();
ElementUtilities elementUtils = compilationInfo.getElementUtilities();
TypeElement clazz = (TypeElement)type;
for (Element ee : type.getEnclosedElements()) {
if (stop != null && stop.isCanceled()) {
Expand All @@ -276,11 +284,11 @@ public static ExecutableElement[] overridesHashCodeAndEquals(CompilationInfo com
}
ExecutableElement method = (ExecutableElement)ee;

if (compilationInfo.getElements().overrides(method, hashCode, clazz)) {
if (!elementUtils.isSynthetic(method) && elements.overrides(method, hashCode, clazz)) {
ret[1] = method;
}

if (compilationInfo.getElements().overrides(method, equals, clazz)) {
if (!elementUtils.isSynthetic(method) && elements.overrides(method, equals, clazz)) {
ret[0] = method;
}
}
Expand Down Expand Up @@ -410,9 +418,7 @@ public static void generateEqualsAndHashCode(WorkingCopy wc, TreePath path, Iter
if (!dt.getTypeArguments().isEmpty()) {
WildcardType wt = wc.getTypes().getWildcardType(null, null);
TypeMirror[] typeArgs = new TypeMirror[dt.getTypeArguments().size()];
for (int i = 0; i < typeArgs.length; i++) {
typeArgs[i] = wt;
}
Arrays.fill(typeArgs, wt);
dt = dt.getEnclosingType().getKind() == TypeKind.DECLARED
? wc.getTypes().getDeclaredType((DeclaredType)dt.getEnclosingType(), te, typeArgs)
: wc.getTypes().getDeclaredType(te, typeArgs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,9 @@
import javax.lang.model.type.TypeMirror;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;

import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.java.source.CodeStyle;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.ElementUtilities;
import org.netbeans.api.java.source.GeneratorUtilities;
Expand All @@ -58,7 +56,6 @@
import org.netbeans.editor.Utilities;
import org.openide.DialogDescriptor;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.util.NbBundle;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.netbeans.modules.java.editor.codegen;

import com.sun.source.tree.Tree;
import java.awt.Dialog;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
Expand Down Expand Up @@ -62,6 +63,11 @@
*/
public class GetterSetterGenerator implements CodeGenerator {

private static final EnumSet<Tree.Kind> TREE_KINDS = EnumSet.copyOf(TreeUtilities.CLASS_TREE_KINDS);
static {
TREE_KINDS.remove(Tree.Kind.RECORD); // no getters/setters for records
}

public static class Factory implements CodeGenerator.Factory {

private static final String ERROR = "<error>"; //NOI18N
Expand All @@ -76,7 +82,7 @@ public List<? extends CodeGenerator> create(Lookup context) {
}
CodeStyle codeStyle = CodeStyle.getDefault(component.getDocument());
TreePath path = context.lookup(TreePath.class);
path = controller.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, path);
path = controller.getTreeUtilities().getPathElementOfKind(TREE_KINDS, path);
if (path == null) {
return ret;
}
Expand Down Expand Up @@ -214,7 +220,7 @@ public void run(WorkingCopy copy) throws IOException {
copy.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
Element e = description.getElementHandle().resolve(copy);
TreePath path = e != null ? copy.getTrees().getPath(e) : copy.getTreeUtilities().pathFor(caretOffset);
path = copy.getTreeUtilities().getPathElementOfKind(TreeUtilities.CLASS_TREE_KINDS, path);
path = copy.getTreeUtilities().getPathElementOfKind(TREE_KINDS, path);
if (path == null) {
String message = NbBundle.getMessage(GetterSetterGenerator.class, "ERR_CannotFindOriginalClass"); //NOI18N
org.netbeans.editor.Utilities.setStatusBoldText(component, message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiFunction;
import java.util.function.Function;

import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
Expand Down Expand Up @@ -193,6 +192,7 @@ public List<ElementHandle<? extends Element>> get() throws InterruptedExceptio
}
}

@Override
public void run() {
List<ElementHandle<? extends Element>> tmp;
if (testOverrideMethodsSelection != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.swing.text.JTextComponent;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.java.source.CompilationController;
Expand Down Expand Up @@ -111,16 +113,32 @@ public List<? extends CodeGenerator> create(Lookup context) {
private final boolean supportsStringBuilder;

@CheckForNull
static ToStringGenerator createToStringGenerator(JTextComponent component, CompilationController controller, Element typeElement, boolean useStringBuilder) {
static ToStringGenerator createToStringGenerator(JTextComponent component, CompilationController controller, TypeElement typeElement, boolean useStringBuilder) {
List<ElementNode.Description> descriptions = new ArrayList<>();

// add ordinal() and name() for enums
if (typeElement.getKind() == ElementKind.ENUM) {
Element enumElement = controller.getTypes().asElement(typeElement.getSuperclass());
for (Element element : ElementFilter.methodsIn(enumElement.getEnclosedElements())) {
Name name = element.getSimpleName();
if (name.contentEquals("ordinal")) { //NOI18N
descriptions.add(0, ElementNode.Description.create(controller, element, null, true, true));
} else if (name.contentEquals("name")) { //NOI18N
descriptions.add(ElementNode.Description.create(controller, element, null, true, true));
}
}
}

for (Element element : typeElement.getEnclosedElements()) {
switch (element.getKind()) {
case METHOD:
if (element.getSimpleName().contentEquals("toString") && ((ExecutableElement) element).getParameters().isEmpty()) { //NOI18N
if (element.getSimpleName().contentEquals("toString") && ((ExecutableElement) element).getParameters().isEmpty() //NOI18N
&& !controller.getElementUtilities().isSynthetic(element)) { // e.g record
return null;
}
break;
case FIELD:
// case RECORD_COMPONENT: // record components will show up as fields for some reason
if (!ERROR.contentEquals(element.getSimpleName()) && !element.getModifiers().contains(Modifier.STATIC)) {
descriptions.add(ElementNode.Description.create(controller, element, null, true, true));
}
Expand Down Expand Up @@ -189,9 +207,9 @@ public void run(WorkingCopy copy) throws IOException {
org.netbeans.editor.Utilities.setStatusBoldText(component, message);
} else {
ClassTree cls = (ClassTree) path.getLeaf();
ArrayList<VariableElement> fields = new ArrayList<>();
List<Element> fields = new ArrayList<>();
for (ElementHandle<? extends Element> elementHandle : panel.getVariables()) {
VariableElement field = (VariableElement) elementHandle.resolve(copy);
Element field = elementHandle.resolve(copy);
if (field == null) {
return;
}
Expand All @@ -209,7 +227,7 @@ public void run(WorkingCopy copy) throws IOException {
}
}

public static MethodTree createToStringMethod(WorkingCopy wc, Iterable<? extends VariableElement> fields, String typeName, boolean useStringBuilder) {
public static MethodTree createToStringMethod(WorkingCopy wc, Iterable<? extends Element> fields, String typeName, boolean useStringBuilder) {
TreeMaker make = wc.getTreeMaker();
Set<Modifier> mods = EnumSet.of(Modifier.PUBLIC);
List<AnnotationTree> annotations = new LinkedList<>();
Expand All @@ -224,7 +242,7 @@ public static MethodTree createToStringMethod(WorkingCopy wc, Iterable<? extends
return make.Method(modifiers, "toString", make.Identifier("String"), Collections.<TypeParameterTree>emptyList(), Collections.<VariableTree>emptyList(), Collections.<ExpressionTree>emptyList(), body, null); //NOI18N
}

private static BlockTree createToStringMethodBody(TreeMaker make, String typeName, Iterable<? extends VariableElement> fields, boolean useStringBuilder) {
private static BlockTree createToStringMethodBody(TreeMaker make, String typeName, Iterable<? extends Element> fields, boolean useStringBuilder) {
List<StatementTree> statements;
if (useStringBuilder) {
statements = createToStringMethodBodyWithStringBuilder(make, typeName, fields);
Expand All @@ -235,24 +253,24 @@ private static BlockTree createToStringMethodBody(TreeMaker make, String typeNam
return body;
}

private static List<StatementTree> createToStringMethodBodyWithPlusOperator(TreeMaker make, String typeName, Iterable<? extends VariableElement> fields) {
private static List<StatementTree> createToStringMethodBodyWithPlusOperator(TreeMaker make, String typeName, Iterable<? extends Element> fields) {
ExpressionTree exp = make.Literal(typeName + '{');
boolean first = true;
for (VariableElement variableElement : fields) {
for (Element variableElement : fields) {
StringBuilder sb = new StringBuilder();
if (!first) {
sb.append(", ");
}
sb.append(variableElement.getSimpleName().toString()).append('=');
exp = make.Binary(Tree.Kind.PLUS, exp, make.Literal(sb.toString()));
exp = make.Binary(Tree.Kind.PLUS, exp, make.Identifier(variableElement.getSimpleName()));
exp = make.Binary(Tree.Kind.PLUS, exp, makeExpression(make, variableElement));
first = false;
}
StatementTree stat = make.Return(make.Binary(Tree.Kind.PLUS, exp, make.Literal('}'))); //NOI18N
return Collections.singletonList(stat);
}

private static List<StatementTree> createToStringMethodBodyWithStringBuilder(TreeMaker make, String typeName, Iterable<? extends VariableElement> fields) {
private static List<StatementTree> createToStringMethodBodyWithStringBuilder(TreeMaker make, String typeName, Iterable<? extends Element> fields) {
List<StatementTree> statements = new ArrayList<>();
final ExpressionTree stringBuilder = make.QualIdent(StringBuilder.class.getName());
NewClassTree newStringBuilder = make.NewClass(null, Collections.emptyList(), stringBuilder, Collections.emptyList(), null);
Expand All @@ -265,7 +283,7 @@ private static List<StatementTree> createToStringMethodBodyWithStringBuilder(Tre
Collections.singletonList(make.Literal(typeName + '{'))
)));
boolean first = true;
for (VariableElement variableElement : fields) {
for (Element variableElement : fields) {
StringBuilder sb = new StringBuilder();
if (!first) {
sb.append(", "); // NOI18N
Expand All @@ -278,7 +296,7 @@ private static List<StatementTree> createToStringMethodBodyWithStringBuilder(Tre
make,
varName,
Collections.singletonList(make.Literal(sb.toString()))),
Collections.singletonList(make.Identifier(variableElement.getSimpleName())))
Collections.singletonList(makeExpression(make, variableElement)))
));
first = false;
}
Expand All @@ -303,4 +321,10 @@ private static MethodInvocationTree createAppendInvocation(TreeMaker make, Expre
);
}

private static ExpressionTree makeExpression(TreeMaker make, Element element) {
return element.getKind() == ElementKind.METHOD
? make.MethodInvocation(Collections.emptyList(), make.Identifier(element.getSimpleName()), Collections.emptyList())
: make.Identifier(element.getSimpleName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public static class Description {
private List<Description> subs;
private String htmlHeader;
private boolean isSelected;
private boolean isSelectable;
private final boolean isSelectable;

public static Description create(List<Description> subs) {
return new Description("<root>", null, null, subs, null, false, false); // NOI18N
Expand All @@ -168,6 +168,7 @@ public static Description create(CompilationInfo info, Element element, List<Des
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case RECORD:
case INTERFACE:
htmlHeader = createHtmlHeader(deprecated, (TypeElement)element);
break;
Expand Down Expand Up @@ -462,6 +463,7 @@ private static String print( TypeMirror tm ) {

private static class DescriptionComparator implements Comparator<Description> {

@Override
public int compare(Description d1, Description d2) {

if ( k2i(d1.elementHandle.getKind()) != k2i(d2.elementHandle.getKind()) ) {
Expand Down
Loading
Loading