|
15 | 15 | import java.lang.reflect.Field; |
16 | 16 | import java.lang.reflect.Method; |
17 | 17 | import java.lang.reflect.Modifier; |
| 18 | +import java.lang.reflect.ParameterizedType; |
| 19 | +import java.lang.reflect.Type; |
18 | 20 | import java.util.ArrayList; |
19 | 21 | import java.util.Collections; |
20 | 22 | import java.util.HashSet; |
@@ -192,31 +194,60 @@ private List<GradleClosure> getPluginClosures(Project project) { |
192 | 194 | for (ExtensionSchema schema : extensionsSchema.getElements()) { |
193 | 195 | TypeOf<?> publicType = schema.getPublicType(); |
194 | 196 | Class<?> concreteClass = publicType.getConcreteClass(); |
195 | | - List<GradleMethod> methods = new ArrayList<>(); |
196 | | - List<GradleField> fields = new ArrayList<>(); |
197 | | - for (Method method : concreteClass.getMethods()) { |
198 | | - String name = method.getName(); |
199 | | - List<String> parameterTypes = new ArrayList<>(); |
200 | | - for (Class<?> parameterType : method.getParameterTypes()) { |
201 | | - parameterTypes.add(parameterType.getName()); |
202 | | - } |
203 | | - methods.add(new DefaultGradleMethod(name, parameterTypes, isDeprecated(method))); |
204 | | - int modifiers = method.getModifiers(); |
205 | | - // See: |
206 | | - // https://docs.gradle.org/current/userguide/custom_gradle_types.html#managed_properties |
207 | | - // we offer managed properties for an abstract getter method |
208 | | - if (name.startsWith("get") && name.length() > 3 && Modifier.isPublic(modifiers) |
209 | | - && Modifier.isAbstract(modifiers)) { |
210 | | - fields.add(new DefaultGradleField(name.substring(3, 4).toLowerCase() + name.substring(4), |
211 | | - isDeprecated(method))); |
| 197 | + closures.addAll(buildClosure(schema.getName(), concreteClass)); |
| 198 | + } |
| 199 | + return closures; |
| 200 | + } |
| 201 | + |
| 202 | + /** |
| 203 | + * @param closureName |
| 204 | + * @param concreteClass |
| 205 | + * @return |
| 206 | + */ |
| 207 | + private List<DefaultGradleClosure> buildClosure(String closureName, Class<?> concreteClass) { |
| 208 | + List<DefaultGradleClosure> closures = new ArrayList<>(); |
| 209 | + List<GradleMethod> methods = new ArrayList<>(); |
| 210 | + List<GradleField> fields = new ArrayList<>(); |
| 211 | + for (Method method : concreteClass.getMethods()) { |
| 212 | + String name = method.getName(); |
| 213 | + List<String> parameterTypes = new ArrayList<>(); |
| 214 | + for (Class<?> parameterType : method.getParameterTypes()) { |
| 215 | + parameterTypes.add(parameterType.getName()); |
| 216 | + } |
| 217 | + |
| 218 | + // check for nested closure methods and include them in the final closure list |
| 219 | + // for completions. |
| 220 | + if (method.getGenericParameterTypes().length == 1) { |
| 221 | + Type parameterType = method.getGenericParameterTypes()[0]; |
| 222 | + if (parameterType.getTypeName().startsWith("org.gradle.api.Action<") |
| 223 | + && (parameterType instanceof ParameterizedType)) { |
| 224 | + Type[] actualTypeArguments = ((ParameterizedType) parameterType).getActualTypeArguments(); |
| 225 | + if (actualTypeArguments.length == 1) { |
| 226 | + try { |
| 227 | + closures.addAll(buildClosure(closureName.concat(".").concat(name), |
| 228 | + concreteClass.getClassLoader().loadClass(actualTypeArguments[0].getTypeName()))); |
| 229 | + } catch (ClassNotFoundException e) { |
| 230 | + // continue if we cannot find the extension class. |
| 231 | + } |
| 232 | + } |
212 | 233 | } |
213 | 234 | } |
214 | | - for (Field field : concreteClass.getFields()) { |
215 | | - fields.add(new DefaultGradleField(field.getName(), isDeprecated(field))); |
| 235 | + |
| 236 | + methods.add(new DefaultGradleMethod(name, parameterTypes, isDeprecated(method))); |
| 237 | + int modifiers = method.getModifiers(); |
| 238 | + // See: |
| 239 | + // https://docs.gradle.org/current/userguide/custom_gradle_types.html#managed_properties |
| 240 | + // we offer managed properties for an abstract getter method |
| 241 | + if (name.startsWith("get") && name.length() > 3 && Modifier.isPublic(modifiers) |
| 242 | + && Modifier.isAbstract(modifiers)) { |
| 243 | + fields.add(new DefaultGradleField(name.substring(3, 4).toLowerCase() + name.substring(4), |
| 244 | + isDeprecated(method))); |
216 | 245 | } |
217 | | - DefaultGradleClosure closure = new DefaultGradleClosure(schema.getName(), methods, fields); |
218 | | - closures.add(closure); |
219 | 246 | } |
| 247 | + for (Field field : concreteClass.getFields()) { |
| 248 | + fields.add(new DefaultGradleField(field.getName(), isDeprecated(field))); |
| 249 | + } |
| 250 | + closures.add(new DefaultGradleClosure(closureName, methods, fields)); |
220 | 251 | return closures; |
221 | 252 | } |
222 | 253 |
|
|
0 commit comments