private MetaClass getFirstTokenMeta(
      Caller caller,
      String firstToken,
      CommandSender commandSender,
      WorkspaceService service,
      MetaClass callerScriptMetaClass,
      MetaClass workspaceMetaClass,
      Workspace workspace,
      Map workspaceVars,
      Map globalVars,
      PreparedScriptProperties properties) {

    if (firstToken.isEmpty() || propertyPattern.matcher(firstToken).matches()) {
      if (firstToken.equals("me")) return InvokerHelper.getMetaClass(commandSender.getClass());
      if (firstToken.equals("this")) return InvokerHelper.getMetaClass(CallerScript.class);
      if (firstToken.equals("_")) {
        Object result = caller.getLastResult();
        if (result == null) return null;
        return InvokerHelper.getMetaClass(result.getClass());
      }
      Class aClass = service.getImportTabCompleteClasses().get(firstToken);
      if (aClass != null) return InvokerHelper.getMetaClass(aClass);
      MetaProperty property = callerScriptMetaClass.getMetaProperty(firstToken);
      if (property != null) return InvokerHelper.getMetaClass(property.getType());
      if (workspaceVars != null)
        for (Object key : workspaceVars.keySet()) {
          String name = key.toString();
          if (name.contains(firstToken)) {
            Object val = workspaceVars.get(key);
            return InvokerHelper.getMetaClass(val.getClass());
          }
        }
      if (globalVars != null)
        for (Object key : globalVars.keySet()) {
          String name = key.toString();
          if (name.contains(firstToken)) {
            Object val = globalVars.get(key);
            return InvokerHelper.getMetaClass(val.getClass());
          }
        }
      if (workspace != null) {
        for (GroovyObject modifier : CallerScript.getDynamicModifiers()) {
          Object[] params = {properties};
          try {
            Map<?, ?> map =
                (Map) modifier.getMetaClass().invokeMethod(modifier, "getPropertyMapFor", params);
            Object value = map.get(firstToken);
            if (!(value instanceof Class)) return null;
            return InvokerHelper.getMetaClass((Class) value);
          } catch (Exception ignored) {
          }
        }
      }
    } else if (methodPattern.matcher(firstToken).matches()) {
      String curMethodName = firstToken.substring(0, firstToken.indexOf('('));
      for (MetaMethod metaMethod : callerScriptMetaClass.getMetaMethods()) {
        String name = metaMethod.getName();
        if (name.equals(curMethodName)) {
          return InvokerHelper.getMetaClass(metaMethod.getReturnType());
        }
      }
      for (MetaMethod metaMethod : workspaceMetaClass.getMetaMethods()) {
        String name = metaMethod.getName();
        if (name.equals(curMethodName)) {
          return InvokerHelper.getMetaClass(metaMethod.getReturnType());
        }
      }
      for (GroovyObject modifier : CallerScript.getDynamicModifiers()) {
        Object[] params = {properties};
        try {
          Map<?, ?> map =
              (Map) modifier.getMetaClass().invokeMethod(modifier, "getMethodMapFor", params);
          Object value = map.get(curMethodName);
          if (!(value instanceof Class)) return null;
          return InvokerHelper.getMetaClass(value);
        } catch (Exception ignored) {
        }
      }
    } else if (firstToken.endsWith("\'") || firstToken.endsWith("\"")) {
      return InvokerHelper.getMetaClass(String.class);
    }
    return null;
  }
 protected Object verifySender(CommandSender sender, Class<?> clazz) {
   if (!clazz.isAssignableFrom(sender.getClass())) {
     throw new IllegalArgumentException("sender must be a " + clazz.getSimpleName());
   }
   return sender;
 }