public static AbstractElement getPredicatedElement(AbstractElement element) {
    if (element.isPredicated()) {
      return element;
    }
    if (element instanceof Assignment) {
      return getPredicatedElement(((Assignment) element).getTerminal());
    }
    if (element instanceof RuleCall) {
      final RuleCall ruleCall = (RuleCall) element;
      final AbstractRule calledRule = ruleCall.getRule();
      Group group = (Group) calledRule.getAlternatives();
      AbstractElement first = group.getElements().get(0);
      AbstractElement result = getPredicatedElement(first);
      if (ruleCall.getArguments().isEmpty()) {
        return result;
      }
      EcoreUtil.Copier copier =
          new EcoreUtil.Copier() {
            private static final long serialVersionUID = 1L;

            @Override
            public EObject copy(EObject eObject) {
              if (eObject instanceof ParameterReference) {
                ParameterReference paramRef = (ParameterReference) eObject;
                Parameter parameter = paramRef.getParameter();
                if (calledRule == GrammarUtil.containingRule(parameter)) {
                  for (NamedArgument givenArgument : ruleCall.getArguments()) {
                    if (givenArgument.getParameter() == parameter) {
                      EObject result = copy(givenArgument.getValue());
                      return result;
                    }
                  }
                  throw new IllegalStateException();
                }
              }
              return super.copy(eObject);
            }
          };
      AbstractElement clone = (AbstractElement) copier.copy(result);
      copier.copyReferences();
      return clone;
    }
    return element;
  }
 @Override
 public Boolean caseRuleCall(RuleCall object) {
   if (!visitedRuleCalls.add(object)) return isOptional(object);
   acceptor.accept(object);
   Set<Parameter> oldConfig = currentConfig;
   try {
     if (!object.getArguments().isEmpty()) {
       currentConfig =
           ParameterConfigHelper.getAssignedArguments(object, getParameterValues(object));
     } else {
       currentConfig = Collections.emptySet();
     }
     Boolean result = doSwitch(object.getRule()) || isOptional(object);
     visitedRuleCalls.remove(object);
     return result;
   } finally {
     currentConfig = oldConfig;
   }
 }
 public static String getArgumentList(final RuleCall ruleCall, final Boolean skipCurrent) {
   final List<NamedArgument> arguments = ruleCall.getArguments();
   AbstractRule abstractRule = ruleCall.getRule();
   boolean needsCurrent =
       !skipCurrent
           && GrammarUtil.isEObjectFragmentRule(abstractRule)
           && !GrammarUtil.isDatatypeRule(abstractRule);
   if (arguments.isEmpty()) {
     if (needsCurrent) {
       return "[$current]";
     }
     return "";
   }
   ParserRule rule = (ParserRule) abstractRule;
   StringBuilder result = new StringBuilder();
   result.append("[");
   if (needsCurrent) {
     result.append("$current, ");
   }
   Joiner.on(", ")
       .appendTo(
           result,
           Iterables.transform(
               rule.getParameters(),
               new Function<Parameter, String>() {
                 @Override
                 public String apply(Parameter input) {
                   for (NamedArgument argument : arguments) {
                     if (argument.getParameter() == input) {
                       return conditionToAntlr(argument.getValue(), true);
                     }
                   }
                   throw new IllegalStateException(
                       "Cannot find argument for parameter: " + input.getName());
                 }
               }));
   result.append("]");
   return result.toString();
 }