code: private void doPMD(@NotNull PMDConfiguration configuration) throws IllegalArgumentException {
          // Load the RuleSets
          RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration, new ResourceLoader());
  
          RuleSets ruleSets = RulesetsFactoryUtils.getRuleSets(configuration.getRuleSets(), ruleSetFactory);
          // this is just double check - we don't get null here
          // instead IllegalArgumentException/RuntimeException is thrown if configuration is wrong
          if (ruleSets == null) {
              return;
          }
  
          Set<Language> languages = getApplicableLanguages(configuration, ruleSets);
          // this throws RuntimeException when modified file does not exist in workspace
          List<DataSource> files = PMD.getApplicableFiles(configuration, languages);
  
          long reportStart = System.nanoTime();
          try {
              renderer = configuration.createRenderer();
              List<Renderer> renderers = new LinkedList<>();
              renderers.add(renderer);
              renderer.start();
  
              Benchmarker.mark(Benchmark.Reporting, System.nanoTime() - reportStart, 0);
  
              RuleContext ctx = new RuleContext();
  
              PMD.processFiles(configuration, ruleSetFactory, files, ctx, renderers);
  
              reportStart = System.nanoTime();
              renderer.end();
          } catch (IOException e) {
              log.error("PMD analysis error", e);
          } finally {
              Benchmarker.mark(Benchmark.Reporting, System.nanoTime() - reportStart, 0);
          }
      }
docs: PMD has terrible design of process configuration. You must use report file with it. I paste this method here and
  improve it.
  
  @throws IllegalArgumentException
  if the configuration is not correct