Registry MarianaTrench::analyze()

in source/MarianaTrench.cpp [61:267]


Registry MarianaTrench::analyze(Context& context) {
  context.artificial_methods =
      std::make_unique<ArtificialMethods>(*context.kinds, context.stores);
  Timer methods_timer;
  LOG(1, "Storing methods...");
  context.methods = std::make_unique<Methods>(context.stores);
  if (context.options->dump_methods()) {
    auto method_list = Json::Value(Json::arrayValue);
    for (const auto* method : *context.methods) {
      method_list.append(method->signature());
    }
    auto methods_path = context.options->methods_output_path();
    LOG(1, "Writing methods to `{}`.", methods_path.native());
    JsonValidation::write_json_file(methods_path, method_list);
  }
  LOG(1, "Stored all methods in {:.2f}s", methods_timer.duration_in_seconds());

  Timer fields_timer;
  LOG(1, "Storing fields...");
  context.fields = std::make_unique<Fields>(context.stores);
  LOG(1, "Stored all fields in {:.2f}s", fields_timer.duration_in_seconds());

  Timer index_timer;
  LOG(1, "Building source index...");
  context.positions =
      std::make_unique<Positions>(*context.options, context.stores);
  context.statistics->log_time("source_index", index_timer);
  LOG(1, "Built source index in {:.2f}s.", index_timer.duration_in_seconds());

  Timer types_timer;
  LOG(1, "Inferring types...");
  context.types = std::make_unique<Types>(*context.options, context.stores);
  context.statistics->log_time("types", types_timer);
  LOG(1, "Inferred types in {:.2f}s.", types_timer.duration_in_seconds());

  Timer class_hierarchies_timer;
  LOG(1, "Building class hierarchies...");
  context.class_hierarchies =
      std::make_unique<ClassHierarchies>(*context.options, context.stores);
  context.statistics->log_time("class_hierarchies", class_hierarchies_timer);
  LOG(1,
      "Built class hierarchies in {:.2f}s.",
      class_hierarchies_timer.duration_in_seconds());

  Timer field_cache_timer;
  LOG(1, "Building fields cache...");
  context.field_cache =
      std::make_unique<FieldCache>(*context.class_hierarchies, context.stores);
  context.statistics->log_time("fields", field_cache_timer);
  LOG(1,
      "Built fields cache in {:.2f}s.",
      field_cache_timer.duration_in_seconds());

  Timer lifecycle_methods_timer;
  LOG(1, "Creating life-cycle wrapper methods...");
  LifecycleMethods::run(
      *context.options, *context.class_hierarchies, *context.methods);
  context.statistics->log_time("lifecycle_methods", lifecycle_methods_timer);
  LOG(1,
      "Created lifecycle methods in {:.2f}s.",
      lifecycle_methods_timer.duration_in_seconds());

  Timer overrides_timer;
  LOG(1, "Building override graph...");
  context.overrides = std::make_unique<Overrides>(
      *context.options, *context.methods, context.stores);
  context.statistics->log_time("overrides", overrides_timer);
  LOG(1,
      "Built override graph in {:.2f}s.",
      overrides_timer.duration_in_seconds());

  Timer call_graph_timer;
  LOG(1, "Building call graph...");
  context.call_graph = std::make_unique<CallGraph>(
      *context.options,
      *context.methods,
      *context.fields,
      *context.types,
      *context.class_hierarchies,
      *context.overrides,
      *context.features);
  context.statistics->log_time("call_graph", call_graph_timer);
  LOG(1,
      "Built call graph in {:.2f}s.",
      call_graph_timer.duration_in_seconds());

  std::vector<Model> generated_models;
  std::vector<FieldModel> generated_field_models;
  if (!context.options->skip_model_generation()) {
    Timer generation_timer;
    LOG(1, "Generating models...");
    auto model_generator_result = ModelGeneration::run(context);
    generated_models = model_generator_result.method_models;
    generated_field_models = model_generator_result.field_models;
    context.statistics->log_time("models_generation", generation_timer);
    LOG(1,
        "Generated {} models and {} field models in {:.2f}s.",
        generated_models.size(),
        generated_field_models.size(),
        generation_timer.duration_in_seconds());
  } else {
    LOG(1, "Skipped model generation.");
  }

  // Add models for artificial methods.
  {
    auto models = context.artificial_methods->models(context);
    generated_models.insert(
        generated_models.end(), models.begin(), models.end());
  }

  Timer registry_timer;
  LOG(1, "Initializing models...");
  auto registry = Registry::load(
      context, *context.options, generated_models, generated_field_models);
  context.statistics->log_time("registry_init", registry_timer);
  LOG(1,
      "Initialized {} models and {} field models in {:.2f}s.",
      registry.models_size(),
      registry.field_models_size(),
      registry_timer.duration_in_seconds());

  Timer rules_timer;
  LOG(1, "Initializing rules...");
  context.rules =
      std::make_unique<Rules>(Rules::load(context, *context.options));
  context.statistics->log_time("rules_init", rules_timer);
  LOG(1,
      "Initialized {} rules in {:.2f}s.",
      context.rules->size(),
      rules_timer.duration_in_seconds());

  Timer kind_pruning_timer;
  LOG(1, "Removing unused Kinds");
  int num_removed = UnusedKinds::remove_unused_kinds(context, registry).size();
  context.statistics->log_time("prune_kinds", rules_timer);
  LOG(1,
      "Removed {} kinds in {:.2f}s.",
      num_removed,
      kind_pruning_timer.duration_in_seconds());

  Timer dependencies_timer;
  LOG(1, "Building dependency graph...");
  context.dependencies = std::make_unique<Dependencies>(
      *context.options,
      *context.methods,
      *context.overrides,
      *context.call_graph,
      registry);
  context.statistics->log_time("dependencies", dependencies_timer);
  LOG(1,
      "Built dependency graph in {:.2f}s.",
      dependencies_timer.duration_in_seconds());

  Timer class_properties_timer;
  context.class_properties = std::make_unique<ClassProperties>(
      *context.options,
      context.stores,
      *context.features,
      *context.dependencies);
  context.statistics->log_time("class_properties", class_properties_timer);
  LOG(1,
      "Created class properties in {:.2f}s.",
      class_properties_timer.duration_in_seconds());

  Timer scheduler_timer;
  LOG(1, "Building the analysis schedule...");
  context.scheduler =
      std::make_unique<Scheduler>(*context.methods, *context.dependencies);
  context.statistics->log_time("scheduler", scheduler_timer);
  LOG(1,
      "Built the analysis schedule in {:.2f}s.",
      scheduler_timer.duration_in_seconds());

  Timer analysis_timer;
  LOG(1, "Analyzing...");
  Interprocedural::run_analysis(context, registry);
  context.statistics->log_time("fixpoint", analysis_timer);
  LOG(1,
      "Analyzed {} models in {:.2f}s. Found {} issues!",
      registry.models_size(),
      analysis_timer.duration_in_seconds(),
      registry.issues_size());

  Timer remove_collapsed_traces_timer;
  LOG(2, "Removing invalid traces due to collapsing...");
  PostprocessTraces::remove_collapsed_traces(registry, context);
  context.statistics->log_time(
      "remove_collapsed_traces", remove_collapsed_traces_timer);
  LOG(2,
      "Removed invalid traces in {:.2f}s.",
      remove_collapsed_traces_timer.duration_in_seconds());

  if (!context.options->skip_source_indexing()) {
    Timer augment_positions_timer;
    LOG(1, "Augmenting positions...");
    Highlights::augment_positions(registry, context);
    context.statistics->log_time("augment_positions", augment_positions_timer);
    LOG(1,
        "Augmented positions in {:.2f}s.",
        augment_positions_timer.duration_in_seconds());
  } else {
    LOG(2, "Skipped augmenting positions.");
  }

  return registry;
}