Skip to content

Commit

Permalink
GROOVY-10177
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Nov 24, 2022
1 parent 64dcf11 commit 2e38fd8
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2021 the original author or authors.
* Copyright 2009-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -83,6 +83,14 @@ public void setSynthetic(boolean b) {}

// ClassNode overrides:

@Override
public void addProperty(PropertyNode pn) {}

@Override
public List<PropertyNode> getProperties() {
return Collections.emptyList();
}

@Override
public List<MethodNode> getDeclaredMethods(String name) {
if (lazyInitDone && !writeProtected) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2021 the original author or authors.
* Copyright 2009-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -83,6 +83,14 @@ public void setSynthetic(boolean b) {}

// ClassNode overrides:

@Override
public void addProperty(PropertyNode pn) {}

@Override
public List<PropertyNode> getProperties() {
return Collections.emptyList();
}

@Override
public List<MethodNode> getDeclaredMethods(String name) {
if (lazyInitDone && !writeProtected) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2021 the original author or authors.
* Copyright 2009-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -83,6 +83,9 @@ public void setSynthetic(boolean b) {}

// ClassNode overrides:

@Override
public void addProperty(PropertyNode pn) {}

@Override
public void addTypeAnnotation(AnnotationNode an) {}

Expand Down Expand Up @@ -119,6 +122,11 @@ public List<MethodNode> getDeclaredMethods(String name) {
return super.getDeclaredMethods(name);
}

@Override
public List<PropertyNode> getProperties() {
return Collections.emptyList();
}

@Override
public void setAnnotated(boolean b) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2021 the original author or authors.
* Copyright 2009-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,9 @@
*/
package org.codehaus.jdt.groovy.internal.compiler.ast;

import static org.eclipse.jdt.groovy.search.AccessorSupport.isGetter;

import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -581,13 +584,13 @@ void setUpGenerics() {

@Override
public void addProperty(final PropertyNode node) {
throw new UnsupportedOperationException("JDTClassNode is immutable, should not be called to add property: " + node.getName());
throw new UnsupportedOperationException("JDTClassNode cannot accept property: " + node.getName());
}

@Override
public PropertyNode addProperty(final String name, final int modifiers, final ClassNode type,
final Expression initialValueExpression, final Statement getterBlock, final Statement setterBlock) {
throw new UnsupportedOperationException("JDTClassNode is immutable, should not be called to add property: " + name);
throw new UnsupportedOperationException("JDTClassNode cannot accept property: " + name);
}

@Override
Expand Down Expand Up @@ -616,6 +619,22 @@ public List<PropertyNode> getProperties() {

nodes.add(clone);
}
} else {
// hydrate properties from getters
for (MethodNode mn : getMethods()) {
if (mn.isPublic() && isGetter(mn) && isGenerated(mn) && !"getMetaClass".equals(mn.getName())) {
String propertyName = Introspector.decapitalize(mn.getName().substring(mn.getName().startsWith("is") ? 2 : 3));
// check for field with same name/type
FieldNode fn = getField(propertyName);
if (fn != null && fn.isPrivate() && fn.getType().equals(mn.getReturnType())) {
PropertyNode pn = new PropertyNode(fn, fn.getModifiers() & (Flags.AccFinal | Flags.AccStatic), null, null);
pn.addAnnotations(fn.getAnnotations());
pn.setDeclaringClass(this);

super.getProperties().add(pn);
}
}
}
}
bits |= PROPERTIES_INITIALIZED;
}
Expand All @@ -625,6 +644,15 @@ public List<PropertyNode> getProperties() {
return Collections.unmodifiableList(super.getProperties());
}

private static boolean isGenerated(MethodNode mn) {
for (AnnotationNode an : mn.getAnnotations()) {
if (an.getClassNode().getName().equals("groovy.transform.Generated")) {
return true;
}
}
return false;
}

@Override
public Iterator<InnerClassNode> getInnerClasses() {
if ((bits & INNER_TYPES_INITIALIZED) == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import static org.codehaus.groovy.ast.tools.GenericsUtils.parseClassNodesFromString;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evaluateExpression;

import java.beans.Introspector;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
Expand Down Expand Up @@ -61,7 +60,6 @@
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.PropertyNode;
import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
Expand Down Expand Up @@ -97,10 +95,10 @@ public class VariableScope implements Iterable<VariableScope.VariableInfo> {
public static final ClassNode VOID_CLASS_NODE = ClassHelper.VOID_TYPE; // void.class
public static final ClassNode VOID_WRAPPER_CLASS_NODE = ClassHelper.void_WRAPPER_TYPE; // Void.class

public static final ClassNode CLASS_CLASS_NODE = ClassHelper.CLASS_Type;
public static final ClassNode OBJECT_CLASS_NODE = ClassHelper.OBJECT_TYPE;
public static final ClassNode GROOVY_OBJECT_CLASS_NODE = ClassHelper.GROOVY_OBJECT_TYPE;
public static final ClassNode GROOVY_SUPPORT_CLASS_NODE = ClassHelper.GROOVY_OBJECT_SUPPORT_TYPE;
public static final ClassNode CLOSURE_CLASS_NODE = ClassHelper.CLOSURE_TYPE;
public static final ClassNode ENUMERATION_CLASS_NODE = ClassHelper.make(Enumeration.class);
public static final ClassNode COLLECTION_CLASS_NODE = ClassHelper.make(Collection.class);
public static final ClassNode ITERABLE_CLASS_NODE = ClassHelper.make(Iterable.class);
Expand All @@ -110,11 +108,12 @@ public class VariableScope implements Iterable<VariableScope.VariableInfo> {
public static final ClassNode ENTRY_CLASS_NODE = ClassHelper.make(Map.Entry.class);
public static final ClassNode RANGE_CLASS_NODE = ClassHelper.RANGE_TYPE;
public static final ClassNode TUPLE_CLASS_NODE = ClassHelper.make(Tuple.class);
public static final ClassNode STRING_CLASS_NODE = ClassHelper.STRING_TYPE;
public static final ClassNode GSTRING_CLASS_NODE = ClassHelper.GSTRING_TYPE;
public static final ClassNode NUMBER_CLASS_NODE = ClassHelper.Number_TYPE;
public static final ClassNode BIG_DECIMAL_CLASS = ClassHelper.BigDecimal_TYPE;
public static final ClassNode BIG_INTEGER_CLASS = ClassHelper.BigInteger_TYPE;
public static final ClassNode NUMBER_CLASS_NODE = ClassHelper.Number_TYPE;
public static final ClassNode STRING_CLASS_NODE = ClassHelper.STRING_TYPE;
public static final ClassNode GSTRING_CLASS_NODE = ClassHelper.GSTRING_TYPE;
public static final ClassNode CLOSURE_CLASS_NODE = ClassHelper.CLOSURE_TYPE;
public static final ClassNode PATTERN_CLASS_NODE = ClassHelper.PATTERN_TYPE;
public static final ClassNode MATCHER_CLASS_NODE = ClassHelper.make(Matcher.class);

Expand Down Expand Up @@ -144,18 +143,6 @@ public class VariableScope implements Iterable<VariableScope.VariableInfo> {
public static final ClassNode FLOAT_CLASS_NODE = ClassHelper.Float_TYPE;
public static final ClassNode DOUBLE_CLASS_NODE = ClassHelper.Double_TYPE;

// don't cache because we have to add properties
public static final ClassNode CLASS_CLASS_NODE = initializeProperties(ClassHelper.makeWithoutCaching(Class.class));

// NOTE: JDTClassNode contains very similar method
private static ClassNode initializeProperties(ClassNode node) {
node.getMethods().stream().filter(AccessorSupport::isGetter).forEach(methodNode -> {
String propertyName = Introspector.decapitalize(methodNode.getName().substring(methodNode.getName().startsWith("is") ? 2 : 3));
node.addProperty(new PropertyNode(propertyName, methodNode.getModifiers(), methodNode.getReturnType(), null, null, null, null));
});
return node;
}

//--------------------------------------------------------------------------

/**
Expand Down

0 comments on commit 2e38fd8

Please sign in to comment.