async function analyzePerAstFile(projectData, astAnalysis, analyzerCfg) {
  const entries = [];
  for (const { file, ast, context: astContext } of projectData.entries) {
    const relativePath = getFilePathRelativeFromRoot(file, projectData.project.path);
    const context = { code: astContext.code, relativePath, projectData, analyzerCfg };

    const fullPath = path.resolve(projectData.project.path, file);
    LogService.debug(`[analyzePerAstFile]: ${fullPath}`);

    // We do a try and catch here, so that unparseable files do not block all metrics we're gathering in a run
    try {
      const { result, meta } = await astAnalysis(ast, context);
      entries.push({ file: relativePath, meta, result });
    } catch (e) {
      LogService.error(`[analyzePerAstFile]: ${fullPath} throws: ${e}`);
    }
  }
  const filteredEntries = entries.filter(({ result }) => Boolean(result.length));
  return filteredEntries;
}
Analyzes one entry: the callback can traverse a given ast for each entry
@param {ProjectInputDataWithMeta} projectData
@param {function} astAnalysis
@param {object} analyzerCfg