docs: protected void visitAccInlineCustomCode(RuleContext context2, AccumulateDescr descr, MethodCallExpr accumulateDSL, PatternDescr basePattern, PatternDescr inputDescr, Set<String> externalDeclrs) {
          context.pushExprPointer(accumulateDSL::addArgument);
  
          String targetClassName = StringUtil.toId(context2.getRuleDescr().getName()) + "Accumulate" + descr.getLine();
          String code = ACCUMULATE_INLINE_FUNCTION.replaceAll("AccumulateInlineFunction", targetClassName);
  
          CompilationUnit templateCU = JavaParser.parse(code);
          ClassOrInterfaceDeclaration templateClass = templateCU.getClassByName(targetClassName).orElseThrow(() -> new RuntimeException("Template did not contain expected type definition."));
          ClassOrInterfaceDeclaration templateContextClass = templateClass.getMembers().stream().filter(m -> m instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclaration) m).getNameAsString().equals("ContextData")).map(ClassOrInterfaceDeclaration.class::cast).findFirst().orElseThrow(() -> new RuntimeException("Template did not contain expected type definition."));
  
          List<String> contextFieldNames = new ArrayList<>();
          MethodDeclaration initMethod = templateClass.getMethodsByName("init").get(0);
          BlockStmt initBlock = JavaParser.parseBlock("{" + descr.getInitCode() + "}");
          List<DeclarationSpec> accumulateDeclarations = new ArrayList<>();
          Set<String> usedExtDeclrs = parseInitBlock( context2, descr, basePattern, templateContextClass, contextFieldNames, initMethod, initBlock, accumulateDeclarations );
  
          boolean useLegacyAccumulate = false;
          Type singleAccumulateType = null;
          MethodDeclaration accumulateMethod = templateClass.getMethodsByName("accumulate").get(0);
          BlockStmt actionBlock = parseBlock(descr.getActionCode());
          Collection<String> allNamesInActionBlock = collectNamesInBlock(context2, actionBlock);
          if (allNamesInActionBlock.size() == 1) {
              String nameExpr = allNamesInActionBlock.iterator().next();
              accumulateMethod.getParameter(1).setName(nameExpr);
              singleAccumulateType = context2.getDeclarationById(nameExpr).get().getType();
          } else {
              allNamesInActionBlock.removeIf( name -> !externalDeclrs.contains( name ) );
              usedExtDeclrs.addAll( allNamesInActionBlock );
              useLegacyAccumulate = true;
          }
  
          Optional<MethodDeclaration> optReverseMethod = Optional.empty();
          if(descr.getReverseCode() != null) {
              BlockStmt reverseBlock = parseBlock(descr.getReverseCode());
              Collection<String> allNamesInReverseBlock = collectNamesInBlock(context2, reverseBlock);
              if (allNamesInReverseBlock.size() == 1) {
                  MethodDeclaration reverseMethod = templateClass.getMethodsByName("reverse").get(0);
                  reverseMethod.getParameter(1).setName(allNamesInReverseBlock.iterator().next());
                  optReverseMethod = Optional.of(reverseMethod);
              } else {
                  allNamesInActionBlock.removeIf( name -> !externalDeclrs.contains( name ) );
                  usedExtDeclrs.addAll( allNamesInActionBlock );
                  useLegacyAccumulate = true;
              }
          }
  
          if ( useLegacyAccumulate || !usedExtDeclrs.isEmpty() ) {
              new LegacyAccumulate(context, descr, basePattern, usedExtDeclrs).build();
              return;
          }
  
          for(DeclarationSpec d : accumulateDeclarations) {
              context2.addDeclaration(d);
          }
  
          writeAccumulateMethod(contextFieldNames, singleAccumulateType, accumulateMethod, actionBlock);
  
          // <result expression>: this is a semantic expression in the selected dialect that is executed after all source objects are iterated.
          MethodDeclaration resultMethod = templateClass.getMethodsByName("getResult").get(0);
          Type returnExpressionType = JavaParser.parseType("java.lang.Object");
          Expression returnExpression = JavaParser.parseExpression(descr.getResultCode());
          if (returnExpression instanceof NameExpr) {
              returnExpression = new EnclosedExpr(returnExpression);
          }
          rescopeNamesToNewScope(new NameExpr("data"), contextFieldNames, returnExpression);
          resultMethod.getBody().get().addStatement(new ReturnStmt(returnExpression));
          MethodDeclaration getResultTypeMethod = templateClass.getMethodsByName("getResultType").get(0);
          getResultTypeMethod.getBody().get().addStatement(new ReturnStmt(new ClassExpr(returnExpressionType)));
  
          if (optReverseMethod.isPresent()) {
              MethodDeclaration supportsReverseMethod = templateClass.getMethodsByName("supportsReverse").get(0);
              supportsReverseMethod.getBody().get().addStatement(JavaParser.parseStatement("return true;"));
  
              BlockStmt reverseBlock = parseBlock(descr.getReverseCode());
              writeAccumulateMethod(contextFieldNames, singleAccumulateType, optReverseMethod.get(), reverseBlock);
          } else {
              MethodDeclaration supportsReverseMethod = templateClass.getMethodsByName("supportsReverse").get(0);
              supportsReverseMethod.getBody().get().addStatement(JavaParser.parseStatement("return false;"));
  
              MethodDeclaration reverseMethod = templateClass.getMethodsByName("reverse").get(0);
              reverseMethod.getBody().get().addStatement(JavaParser.parseStatement("throw new UnsupportedOperationException(\"This function does not support reverse.\");"));
          }
  
          // add resulting accumulator class into the package model
          this.packageModel.addGeneratedPOJO(templateClass);
  
          final MethodCallExpr functionDSL = new MethodCallExpr(null, ACC_FUNCTION_CALL);
          functionDSL.addArgument(new ClassExpr(JavaParser.parseType(targetClassName)));
          functionDSL.addArgument(context.getVarExpr(inputDescr.getIdentifier()));
  
          final String bindingId = basePattern.getIdentifier();
          final MethodCallExpr asDSL = new MethodCallExpr(functionDSL, BIND_AS_CALL);
          asDSL.addArgument( context.getVarExpr( bindingId ) );
          accumulateDSL.addArgument(asDSL);
  
          context.popExprPointer();
      }