class PortugueseProclisisFilter extends RuleFilter {
  protected PortugueseSynthesizer getSynthesizer() {
    return PortugueseSynthesizer.INSTANCE;
  }

  @Override
  public RuleMatch acceptRuleMatch(RuleMatch match, Map<String, String> arguments, int patternTokenPos,
                                   AnalyzedTokenReadings[] patternTokens, List<Integer> tokenPositions) throws IOException {<FILL_FUNCTION_BODY>}
}

    AnalyzedTokenReadings encliticVerbTokenReadings = patternTokens[patternTokens.length - 1];
    HashSet<String> suggestions = new HashSet<>(Collections.emptyList());
    for (AnalyzedToken at : encliticVerbTokenReadings.getReadings()) {
      String posTag = at.getPOSTag();
      String oldToken = at.getToken();
      assert posTag != null;
      String[] tagParts = posTag.split(":");
      String verbTag = tagParts[0];
      String newVerb = getSynthesizer().synthesize(at, verbTag)[0];
      String[] oldTokenParts = oldToken.split("-");
      // Includes only the relevant part of the verb; i.e. for mesoclitics, we ignore the ending
      String oldVerb = oldTokenParts[0];
      String oldPronoun = oldTokenParts[1];
      List<String> newPronounForms = new ArrayList<>(Collections.emptyList());
      switch (oldPronoun) {
        case "lo":
        case "no":
          newPronounForms.add("o");
          break;
        case "la":
        case "na":
          newPronounForms.add("a");
          break;
        case "los":
          newPronounForms.add("os");
          break;
        case "las":
        case "nas":
          newPronounForms.add("as");
          break;
        case "nos":
          newPronounForms.add("nos");
          if (oldVerb.endsWith("m") || oldVerb.endsWith("ão") || oldVerb.endsWith("õe")) {
            newPronounForms.add("os");
          }
          break;
        default:
          newPronounForms.add(oldPronoun);
      }
      for (String newPronoun : newPronounForms) {
        String suggestion = newPronoun + " " + newVerb;
        suggestions.add(suggestion);
      }
    }
    match.setSuggestedReplacements(new ArrayList<>(suggestions));
    return match;
  
<methods>public non-sealed void <init>() ,public abstract org.languagetool.rules.RuleMatch acceptRuleMatch(org.languagetool.rules.RuleMatch, Map<java.lang.String,java.lang.String>, int, org.languagetool.AnalyzedTokenReadings[], List<java.lang.Integer>) throws java.io.IOException,public boolean matches(Map<java.lang.String,java.lang.String>, org.languagetool.AnalyzedTokenReadings[], int, List<java.lang.Integer>) throws java.io.IOException<variables>