public void getHelp(Caller caller, Workspace workspace, LinkedList<String> tokens) { WorkspaceService service = plugin.getWorkspaceService(); String source = service.getWorkspaceName(caller.getSender()); String firstToken = tokens.pollFirst(); if (firstToken == null) firstToken = ""; MetaClass callerScriptMetaClass = InvokerHelper.getMetaClass(CallerScript.class); MetaClass workspaceMetaClass = InvokerHelper.getMetaClass(Workspace.class); Map workspaceVars = null; if (workspace != null) workspaceVars = workspace.getBinding().getVariables(); Map globalVars = service.getBinding().getVariables(); PreparedScriptProperties properties = new PreparedScriptProperties(); properties.setCaller(caller); properties.setServer(plugin.getServer()); properties.setWorkspace(workspace); if (tokens.isEmpty()) { // get current method or class if (firstToken.equals("_")) { Object result = caller.getLastResult(); String type = "null"; if (result != null) type = result.getClass().getName(); caller.sendPrintMessage("Last result: " + AQUA + type + RESET, source); return; } MetaProperty prop = callerScriptMetaClass.getMetaProperty(firstToken); if (prop != null) { caller.sendPrintMessage( String.format( "Script property %s: %s", YELLOW + prop.getName() + RESET, AQUA + prop.getType().getName() + RESET), source); return; } Class compClass = service.getImportTabCompleteClasses().get(firstToken); if (compClass != null) { String type = "Class"; if (compClass.isInterface()) type = "Interface"; else if (compClass.isEnum()) type = "Enum class"; StringBuilder buf = new StringBuilder(); Class superClass = compClass.getSuperclass(); buf.append(type).append(" ").append(YELLOW).append(compClass.getName()).append(RESET); if (superClass != null) { buf.append(" extends ").append(AQUA).append(superClass.getName()).append(RESET); } caller.sendPrintMessage(buf, source); return; } for (MetaMethod metaMethod : callerScriptMetaClass.getMetaMethods()) { String name = metaMethod.getName(); String methodEnd = "("; if (metaMethod.isValidMethod(new Class[] {Closure.class})) methodEnd = "{"; else if (metaMethod.getParameterTypes().length == 0) methodEnd = "()"; if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Script meta method ") .append(YELLOW) .append(metaMethod.getName()) .append(RESET); buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName()); buf.append(RESET).append('\n'); Class[] types = metaMethod.getNativeParameterTypes(); buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n'); for (Class type : types) buf.append(AQUA).append(type.getName()).append('\n').append(RESET); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } int args = metaMethod.getParameterTypes().length; if ((name.startsWith("get") && args == 0 || name.startsWith("set") && args == 1) && name.length() > 3) { String propertyName = getPropertyName(name); if (propertyName != null && propertyName.equals(firstToken)) { caller.sendPrintMessage( String.format( "Script meta getter %s returns %s", YELLOW + name + "()" + RESET, AQUA + metaMethod.getReturnType().getName() + RESET), source); } } } for (MetaMethod metaMethod : workspaceMetaClass.getMetaMethods()) { String name = metaMethod.getName(); String methodEnd = "("; if (metaMethod.isValidMethod(new Class[] {Closure.class})) methodEnd = "{"; else if (metaMethod.getParameterTypes().length == 0) methodEnd = "()"; if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Workspace meta method ") .append(YELLOW) .append(metaMethod.getName()) .append(RESET); buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName()); buf.append(RESET).append('\n'); Class[] types = metaMethod.getNativeParameterTypes(); buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n'); for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } } for (Method method : CallerScript.class.getMethods()) { String name = method.getName(); String methodEnd = "("; Class<?>[] params = method.getParameterTypes(); if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{"; else if (params.length == 0) methodEnd = "()"; if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Script method ").append(YELLOW).append(method.getName()).append(RESET); buf.append(" returns ").append(AQUA).append(method.getReturnType().getName()); buf.append(RESET).append('\n'); buf.append("arguments: ").append(YELLOW).append(params.length).append(RESET).append('\n'); for (Class<?> type : params) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } int args = params.length; if ((name.startsWith("get") && args == 0 || name.startsWith("set") && args == 1) && name.length() > 3) { String propertyName = getPropertyName(name); if (propertyName != null && propertyName.equals(firstToken)) { caller.sendPrintMessage( String.format( "Script getter %s returns %s", YELLOW + name + "()" + RESET, AQUA + method.getReturnType().getName() + RESET), source); } } } for (Method method : Workspace.class.getMethods()) { String name = method.getName(); String methodEnd = "("; Class<?>[] params = method.getParameterTypes(); if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{"; else if (params.length == 0) methodEnd = "()"; if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Workspace method ").append(YELLOW).append(method.getName()).append(RESET); buf.append(" returns ").append(AQUA).append(method.getReturnType().getName()); buf.append(RESET).append('\n'); buf.append("arguments: ").append(YELLOW).append(params.length).append(RESET).append('\n'); for (Class<?> type : params) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } } if (workspaceVars != null) { Object result = workspaceVars.get(firstToken); if (result != null || workspaceVars.containsKey(firstToken)) { caller.sendPrintMessage( String.format( "Workspace variable %s: %s", YELLOW + firstToken + RESET, AQUA + (result == null ? "null" : result.getClass().getName()) + RESET), source); return; } } if (globalVars != null) { Object result = globalVars.get(firstToken); if (result != null || globalVars.containsKey(firstToken)) { caller.sendPrintMessage( String.format( "Workspace variable %s: %s", YELLOW + firstToken + RESET, AQUA + (result == null ? "null" : result.getClass().getName()) + RESET), source); return; } } for (GroovyObject modifier : CallerScript.getDynamicModifiers()) { Object[] params = {properties}; try { Map<?, ?> map = (Map) modifier.getMetaClass().invokeMethod(modifier, "getPropertyMapFor", params); Object result = map.get(firstToken); if (result != null || map.containsKey(firstToken)) { Class resultClass = result instanceof Class ? (Class) result : null; caller.sendPrintMessage( String.format( "Dynamic variable %s: %s", YELLOW + firstToken + RESET, AQUA + (resultClass == null ? "unknown type" : resultClass.getName()) + RESET), source); } } catch (Exception ignored) { } try { Map<?, ?> map = (Map) modifier.getMetaClass().invokeMethod(modifier, "getMethodMapFor", params); String funToken = firstToken; if (funToken.endsWith("(")) funToken = firstToken.substring(0, funToken.length() - 1); Object result = map.get(funToken); if (result != null || map.containsKey(funToken)) { Class resultClass = result instanceof Class ? (Class) result : null; caller.sendPrintMessage( String.format( "Dynamic function %s: %s", YELLOW + firstToken + RESET, AQUA + (resultClass == null ? "unknown type" : resultClass.getName()) + RESET), source); } } catch (Exception ignored) { } } return; } MetaClass metaClass = getFirstTokenMeta( caller, firstToken, caller.getSender(), service, callerScriptMetaClass, workspaceMetaClass, workspace, workspaceVars, globalVars, properties); boolean classHook = tokens.size() <= 1 && service.getImportTabCompleteClasses().containsKey(firstToken); metaClass = skipTokens(tokens, metaClass); if (metaClass == null) return; // select property or method of last metaclass String token = tokens.pollFirst(); Class theClass = metaClass.getTheClass(); MetaProperty metaProperty = metaClass.getMetaProperty(token); if (metaProperty != null) { caller.sendPrintMessage( String.format( "Meta property %s: %s", YELLOW + token + RESET, AQUA + metaProperty.getType().getName() + RESET), source); } for (MetaMethod metaMethod : metaClass.getMetaMethods()) { String name = metaMethod.getName(); String methodEnd = "("; Class<?>[] params = metaMethod.getNativeParameterTypes(); if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{"; else if (params.length == 0) methodEnd = "()"; if (token.equals(name) || token.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Meta method ").append(YELLOW).append(metaMethod.getName()).append(RESET); buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName()); buf.append(RESET).append('\n'); Class[] types = metaMethod.getNativeParameterTypes(); buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n'); for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } int args = params.length; if (name.startsWith("get") && args == 0 && name.length() > 3) { String propertyName = getPropertyName(name); if (propertyName != null && propertyName.equals(token)) { caller.sendPrintMessage( String.format( "Meta getter %s returns %s", YELLOW + name + "()" + RESET, AQUA + metaMethod.getReturnType().getName() + RESET), source); } } } for (Method method : theClass.getMethods()) { String name = method.getName(); String methodEnd = "("; Class<?>[] params = method.getParameterTypes(); if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{"; else if (params.length == 0) methodEnd = "()"; if (token.equals(name) || token.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Method ").append(YELLOW).append(method.getName()).append(RESET); buf.append(" returns ").append(AQUA).append(method.getReturnType().getName()); buf.append(RESET).append('\n'); Class[] types = method.getParameterTypes(); buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n'); for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } int args = params.length; if (name.startsWith("get") && args == 0 && name.length() > 3) { String propertyName = getPropertyName(name); if (propertyName != null && propertyName.equals(token)) { caller.sendPrintMessage( String.format( "Getter %s returns %s", YELLOW + name + "()" + RESET, AQUA + method.getReturnType().getName() + RESET), source); } } } if (Enum.class.isAssignableFrom(theClass)) { Enum[] enumValues = getEnumValues(theClass); if (enumValues != null) for (Enum anEnum : enumValues) { String name = anEnum.name(); if (name.equals(token)) { caller.sendPrintMessage( String.format( "Enum value %s: %s", YELLOW + name + RESET, AQUA + theClass.getName() + RESET), source); } } } if (classHook) { MetaProperty property = InvokerHelper.getMetaClass(Class.class).getMetaProperty(token); if (property != null) { caller.sendPrintMessage( String.format( "Meta property %s: %s", YELLOW + token + RESET, AQUA + property.getType().getName() + RESET), source); } for (MetaMethod metaMethod : InvokerHelper.getMetaClass(Class.class).getMetaMethods()) { String name = metaMethod.getName(); String methodEnd = "("; Class<?>[] params = metaMethod.getNativeParameterTypes(); if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{"; else if (params.length == 0) methodEnd = "()"; if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Method ").append(YELLOW).append(metaMethod.getName()).append(RESET); buf.append(" returns ").append(AQUA).append(metaMethod.getReturnType().getName()); buf.append(RESET).append('\n'); Class[] types = metaMethod.getNativeParameterTypes(); buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n'); for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } } for (Method method : Class.class.getMethods()) { String name = method.getName(); String methodEnd = "("; Class<?>[] params = method.getParameterTypes(); if (params.length == 1 && Closure.class.isAssignableFrom(params[0])) methodEnd = "{"; else if (params.length == 0) methodEnd = "()"; if (firstToken.equals(name) || firstToken.equals(name + methodEnd)) { StringBuilder buf = new StringBuilder(); buf.append("Method ").append(YELLOW).append(method.getName()).append(RESET); buf.append(" returns ").append(AQUA).append(method.getReturnType().getName()); buf.append(RESET).append('\n'); Class[] types = method.getParameterTypes(); buf.append("arguments: ").append(YELLOW).append(types.length).append(RESET).append('\n'); for (Class type : types) buf.append(AQUA).append(type.getName()).append(RESET).append('\n'); buf.deleteCharAt(buf.length() - 1); caller.sendPrintMessage(buf, source); } } } }
public <T> Class<? extends T> generate(Class<T> type) { Map<Class, Class> cache = GENERATED_CLASSES.get(getClass()); if (cache == null) { cache = new HashMap<Class, Class>(); GENERATED_CLASSES.put(getClass(), cache); } Class generatedClass = cache.get(type); if (generatedClass != null) { return generatedClass; } if (Modifier.isPrivate(type.getModifiers())) { throw new GradleException( String.format( "Cannot create a proxy class for private class '%s'.", type.getSimpleName())); } if (Modifier.isAbstract(type.getModifiers())) { throw new GradleException( String.format( "Cannot create a proxy class for abstract class '%s'.", type.getSimpleName())); } Class<? extends T> subclass; try { ClassBuilder<T> builder = start(type); boolean isConventionAware = type.getAnnotation(NoConventionMapping.class) == null; boolean isDynamicAware = type.getAnnotation(NoDynamicObject.class) == null; builder.startClass(isConventionAware, isDynamicAware); if (isDynamicAware && !DynamicObjectAware.class.isAssignableFrom(type)) { builder.mixInDynamicAware(); } if (isDynamicAware && !GroovyObject.class.isAssignableFrom(type)) { builder.mixInGroovyObject(); } if (isDynamicAware) { builder.addDynamicMethods(); } if (isConventionAware && !IConventionAware.class.isAssignableFrom(type)) { builder.mixInConventionAware(); } Class noMappingClass = Object.class; for (Class<?> c = type; c != null && noMappingClass == Object.class; c = c.getSuperclass()) { if (c.getAnnotation(NoConventionMapping.class) != null) { noMappingClass = c; } } Collection<String> skipProperties = Arrays.asList("metaClass", "conventionMapping", "convention", "asDynamicObject"); MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(type); for (MetaProperty property : metaClass.getProperties()) { if (skipProperties.contains(property.getName())) { continue; } if (property instanceof MetaBeanProperty) { MetaBeanProperty metaBeanProperty = (MetaBeanProperty) property; MetaMethod getter = metaBeanProperty.getGetter(); if (getter == null) { continue; } if (Modifier.isFinal(getter.getModifiers()) || Modifier.isPrivate(getter.getModifiers())) { continue; } if (getter.getReturnType().isPrimitive()) { continue; } Class declaringClass = getter.getDeclaringClass().getTheClass(); if (declaringClass.isAssignableFrom(noMappingClass)) { continue; } builder.addGetter(metaBeanProperty); MetaMethod setter = metaBeanProperty.getSetter(); if (setter == null) { continue; } if (Modifier.isFinal(setter.getModifiers()) || Modifier.isPrivate(setter.getModifiers())) { continue; } builder.addSetter(metaBeanProperty); } } for (Constructor<?> constructor : type.getConstructors()) { if (Modifier.isPublic(constructor.getModifiers())) { builder.addConstructor(constructor); } } subclass = builder.generate(); } catch (Throwable e) { throw new GradleException( String.format("Could not generate a proxy class for class %s.", type.getName()), e); } cache.put(type, subclass); return subclass; }