<commit_before>// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <set>
#include <unordered_set>
#include <utility>
#include <vector>

#include "elang/compiler/analysis/class_tree_builder.h"

#include "elang/base/zone_allocated.h"
#include "elang/base/zone_vector.h"
#include "elang/compiler/analysis/analysis.h"
#include "elang/compiler/analysis/name_resolver.h"
#include "elang/compiler/analysis/name_resolver_editor.h"
#include "elang/compiler/ast/class.h"
#include "elang/compiler/ast/namespace.h"
#include "elang/compiler/ast/types.h"
#include "elang/compiler/compilation_session.h"
#include "elang/compiler/modifiers.h"
#include "elang/compiler/predefined_names.h"
#include "elang/compiler/public/compiler_error_code.h"
#include "elang/compiler/semantics/editor.h"
#include "elang/compiler/semantics/factory.h"
#include "elang/compiler/semantics/nodes.h"

namespace elang {
namespace compiler {

namespace {

bool IsFixed(sm::Semantic* semantic) {
  if (auto const clazz = semantic->as<sm::Class>())
    return clazz->has_base();
  return true;
}

bool IsNamespaceOrType(sm::Semantic* semantic) {
  return semantic->is<sm::Type>() || semantic->is<sm::Namespace>();
}

}  // namespace

//////////////////////////////////////////////////////////////////////
//
// ClassTreeBuilder::ClassData
//
class ClassTreeBuilder::ClassData final : public ZoneAllocated {
 public:
  ClassData(Zone* zone, sm::Class* clazz);
  ~ClassData() = delete;

  const ZoneVector<ast::ClassBody*>& class_bodies() const {
    return class_bodies_;
  }

  void AddClassBody(ast::ClassBody* class_body);

 private:
  sm::Class* const class_;
  ZoneVector<ast::ClassBody*> class_bodies_;

  DISALLOW_COPY_AND_ASSIGN(ClassData);
};

ClassTreeBuilder::ClassData::ClassData(Zone* zone, sm::Class* clazz)
    : class_(clazz), class_bodies_(zone) {
}

void ClassTreeBuilder::ClassData::AddClassBody(ast::ClassBody* class_body) {
  DCHECK(std::find(class_bodies_.begin(), class_bodies_.end(), class_body) ==
         class_bodies_.end());
  class_bodies_.push_back(class_body);
}

//////////////////////////////////////////////////////////////////////
//
// ClassTreeBuilder
//
ClassTreeBuilder::ClassTreeBuilder(NameResolver* resolver, sm::Editor* editor)
    : CompilationSessionUser(resolver->session()),
      resolver_editor_(new NameResolverEditor(resolver)),
      semantic_editor_(editor) {
}

ClassTreeBuilder::~ClassTreeBuilder() {
}

void ClassTreeBuilder::AnalyzeClassBody(ast::ClassBody* node) {
  auto const clazz = SemanticOf(node)->as<sm::Class>();
  if (auto const ns = node->parent()->as<ast::NamespaceBody>()) {
    if (ns->loaded_) {
      DCHECK(IsFixed(clazz)) << clazz;
      return;
    }
  }
  DCHECK(!IsFixed(clazz)) << clazz;
  auto const outer = node->parent()->as<ast::ContainerNode>();
  auto const class_data = ClassDataFor(clazz);
  class_data->AddClassBody(node);
  if (auto const outer_class = clazz->outer()->as<sm::Class>())
    MarkDepdency(clazz, outer_class);
  for (auto const base_class_name : node->base_class_names()) {
    auto const present = Resolve(node, base_class_name, outer);
    if (!present) {
      unresolved_names_.insert(base_class_name);
      continue;
    }
    auto const base_class = present->as<sm::Class>();
    if (!base_class)
      continue;
    if (clazz == base_class)
      Error(ErrorCode::ClassTreeBaseClassSelf, node, base_class_name);
    MarkDepdency(clazz, base_class);
  }
  auto const default_base_class = DefaultBaseClassFor(clazz);
  if (!default_base_class || clazz == default_base_class)
    return;
  MarkDepdency(clazz, default_base_class);
}

ClassTreeBuilder::ClassData* ClassTreeBuilder::ClassDataFor(sm::Class* clazz) {
  auto const it = class_data_map_.find(clazz);
  if (it != class_data_map_.end())<commit_msg>elang/compiler/analysis: Make |ClassTreeBuilder| not to use |ast::NamespaceBody::loaded_|.<commit_after>// Copyright 2015 Project Vogue. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <set>
#include <unordered_set>
#include <utility>
#include <vector>

#include "elang/compiler/analysis/class_tree_builder.h"

#include "elang/base/zone_allocated.h"
#include "elang/base/zone_vector.h"
#include "elang/compiler/analysis/analysis.h"
#include "elang/compiler/analysis/name_resolver.h"
#include "elang/compiler/analysis/name_resolver_editor.h"
#include "elang/compiler/ast/class.h"
#include "elang/compiler/ast/namespace.h"
#include "elang/compiler/ast/types.h"
#include "elang/compiler/compilation_session.h"
#include "elang/compiler/modifiers.h"
#include "elang/compiler/predefined_names.h"
#include "elang/compiler/public/compiler_error_code.h"
#include "elang/compiler/semantics/editor.h"
#include "elang/compiler/semantics/factory.h"
#include "elang/compiler/semantics/nodes.h"

namespace elang {
namespace compiler {

namespace {

bool IsFixed(sm::Semantic* semantic) {
  if (auto const clazz = semantic->as<sm::Class>())
    return clazz->has_base();
  return true;
}

bool IsNamespaceOrType(sm::Semantic* semantic) {
  return semantic->is<sm::Type>() || semantic->is<sm::Namespace>();
}

}  // namespace

//////////////////////////////////////////////////////////////////////
//
// ClassTreeBuilder::ClassData
//
class ClassTreeBuilder::ClassData final : public ZoneAllocated {
 public:
  ClassData(Zone* zone, sm::Class* clazz);
  ~ClassData() = delete;

  const ZoneVector<ast::ClassBody*>& class_bodies() const {
    return class_bodies_;
  }

  void AddClassBody(ast::ClassBody* class_body);

 private:
  sm::Class* const class_;
  ZoneVector<ast::ClassBody*> class_bodies_;

  DISALLOW_COPY_AND_ASSIGN(ClassData);
};

ClassTreeBuilder::ClassData::ClassData(Zone* zone, sm::Class* clazz)
    : class_(clazz), class_bodies_(zone) {
}

void ClassTreeBuilder::ClassData::AddClassBody(ast::ClassBody* class_body) {
  DCHECK(std::find(class_bodies_.begin(), class_bodies_.end(), class_body) ==
         class_bodies_.end());
  class_bodies_.push_back(class_body);
}

//////////////////////////////////////////////////////////////////////
//
// ClassTreeBuilder
//
ClassTreeBuilder::ClassTreeBuilder(NameResolver* resolver, sm::Editor* editor)
    : CompilationSessionUser(resolver->session()),
      resolver_editor_(new NameResolverEditor(resolver)),
      semantic_editor_(editor) {
}

ClassTreeBuilder::~ClassTreeBuilder() {
}

void ClassTreeBuilder::AnalyzeClassBody(ast::ClassBody* node) {
  auto const clazz = SemanticOf(node)->as<sm::Class>();
  DCHECK(!IsFixed(clazz)) << clazz;
  auto const outer = node->parent()->as<ast::ContainerNode>();
  auto const class_data = ClassDataFor(clazz);
  class_data->AddClassBody(node);
  if (auto const outer_class = clazz->outer()->as<sm::Class>())
    MarkDepdency(clazz, outer_class);
  for (auto const base_class_name : node->base_class_names()) {
    auto const present = Resolve(node, base_class_name, outer);
    if (!present) {
      unresolved_names_.insert(base_class_name);
      continue;
    }
    auto const base_class = present->as<sm::Class>();
    if (!base_class)
      continue;
    if (clazz == base_class)
      Error(ErrorCode::ClassTreeBaseClassSelf, node, base_class_name);
    MarkDepdency(clazz, base_class);
  }
  auto const default_base_class = DefaultBaseClassFor(clazz);
  if (!default_base_class || clazz == default_base_class)
    return;
  MarkDepdency(clazz, default_base_class);
}

ClassTreeBuilder::ClassData* ClassTreeBuilder::ClassDataFor(sm::Class* clazz) {
  auto const it = class_data_map_.find(clazz);
  if (it != class_data_map_.end())
{'fraction_non_alphanumeric': 0.1732068607068607, 'fraction_numerical': 0.0010395010395010396, 'mean_word_length': 4.360027855153203, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4033406', 'n_tokens_mistral': 2508, 'n_tokens_neox': 2466, 'n_words': 454}