<commit_before>package Mojolicious::Routes;
use Mojo::Base 'Mojolicious::Routes::Route';

use List::Util 'first';
use Mojo::Cache;
use Mojo::Loader;
use Mojo::Util 'camelize';
use Mojolicious::Routes::Match;
use Scalar::Util 'weaken';

has base_classes => sub { [qw(Mojolicious::Controller Mojo)] };
has cache        => sub { Mojo::Cache->new };
has [qw(conditions shortcuts)] => sub { {} };
has hidden     => sub { [qw(attr has new tap)] };
has namespaces => sub { [] };

sub add_condition { shift->_add(conditions => @_) }
sub add_shortcut  { shift->_add(shortcuts  => @_) }

sub auto_render {
  my ($self, $c) = @_;
  my $stash = $c->stash;
  return if $stash->{'mojo.rendered'};
  $c->render_maybe or $stash->{'mojo.routed'} or $c->render_not_found;
}

sub continue {
  my ($self, $c) = @_;

  my $match   = $c->match;
  my $stack   = $match->stack;
  my $current = $match->current;
  return 1 unless my $field = $stack->[$current];
  my $last = !$stack->[++$current];

  # Merge captures into stash
  my @keys  = keys %$field;
  my $stash = $c->stash;
  @{$stash}{@keys} = @{$stash->{'mojo.captures'}}{@keys} = values %$field;

  my $continue
    = $field->{cb}
    ? $self->_callback($c, $field, $last)
    : $self->_controller($c, $field, $last);
  $match->current($current);

  # Break the chain
  return undef if !$last && !$continue;

  # Continue
  return $self->continue($c);
}

sub dispatch {
  my ($self, $c) = @_;

  # Path (partial path gets priority)
  my $req  = $c->req;
  my $path = $c->stash->{path};
  if (defined $path) { $path = "/$path" if $path !~ m!^/! }
  else               { $path = $req->url->path->to_route }

  # Method (HEAD will be treated as GET)
  my $method = uc $req->method;
  $method = 'GET' if $method eq 'HEAD';

  # Check cache
  my $cache = $self->cache;
  my $ws    = $c->tx->is_websocket ? 1 : 0;
  my $match = Mojolicious::Routes::Match->new(root => $self);
  $c->match($match);
  if ($cache && (my $cached = $cache->get("$method:$path:$ws"))) {
    $match->endpoint($cached->{endpoint})->stack($cached->{stack});
  }

  # Check routes
  else {
    my $options = {method => $method, path => $path, websocket => $ws};
    $match->match($c => $options);

    # Cache routes without conditions
    if ($cache && (my $endpoint = $match->endpoint)) {
      my $result = {endpoint => $endpoint, stack => $match->stack};
      $cache->set("$method:$path:$ws" => $result)
        unless $endpoint->has_conditions;
    }
  }

  return undef unless @{$c->match->stack};
  $self->auto_render($c) if $self->continue($c);
  return 1;
}

sub hide { push @{shift->hidden}, @_ }

sub is_hidden {
  my ($self, $method) = @_;
  my $h = $self->{hiding} ||= {map { $_ => 1 } @{$self->hidden}};
  return !!($h->{$method} || index($method, '_') == 0 || $method !~ /[a-z]/);
}

sub lookup {
  my ($self, $name) = @_;
  my $reverse = $self->{reverse} ||= {};
  return $reverse->{$name} if exists $reverse->{$name};
  return undef unless my $route = $self->find($name);
  return $reverse->{$name} = $route;
}

sub route {
  shift->add_child(Mojolicious::Routes::Route->new(@_))->children->[-1];
}

sub _action { shift->plugins->emit_chain(around_action => @_) }

sub _add {
  my ($self, $attr, $name, $cb) = @_;
  $self->$attr->{$name} = $cb;
  return $self;
}

sub _callback {
  my ($self, $c, $field, $last) = @_;
  $c->stash->{'mojo.routed'}++ if $last;
  my $app = $c->app;
  $app->log->debug('Routing to a callback.');
  return _action($app, $c, $field->{cb}, $last);
}

sub _class {
  my ($self, $c, $field) = @_;

  # Application instance
  return $field->{app} if ref $field->{app};

  # Application class
  my @classes;
  my $class = $field->{controller} ? camelize($field->{controller}) : '';
  if ($field->{app}) { push @classes, $field->{app} }

  # Specific namespace
  elsif (defined(my $namespace = $field->{namespace})) {
    if ($class) { push @classes, $namespace ? "${namespace}::$class" : $class }
    elsif ($namespace) { push @classes, $namespace }
  }

  # All namespaces<commit_msg>small optimization<commit_after>package Mojolicious::Routes;
use Mojo::Base 'Mojolicious::Routes::Route';

use List::Util 'first';
use Mojo::Cache;
use Mojo::Loader;
use Mojo::Util 'camelize';
use Mojolicious::Routes::Match;
use Scalar::Util 'weaken';

has base_classes => sub { [qw(Mojolicious::Controller Mojo)] };
has cache        => sub { Mojo::Cache->new };
has [qw(conditions shortcuts)] => sub { {} };
has hidden     => sub { [qw(attr has new tap)] };
has namespaces => sub { [] };

sub add_condition { shift->_add(conditions => @_) }
sub add_shortcut  { shift->_add(shortcuts  => @_) }

sub auto_render {
  my ($self, $c) = @_;
  my $stash = $c->stash;
  return if $stash->{'mojo.rendered'};
  $c->render_maybe or $stash->{'mojo.routed'} or $c->render_not_found;
}

sub continue {
  my ($self, $c) = @_;

  my $match   = $c->match;
  my $stack   = $match->stack;
  my $current = $match->current;
  return 1 unless my $field = $stack->[$current];
  my $last = !$stack->[++$current];

  # Merge captures into stash
  my @keys  = keys %$field;
  my $stash = $c->stash;
  @{$stash}{@keys} = @{$stash->{'mojo.captures'}}{@keys} = values %$field;

  my $continue;
  if (my $cb = $field->{cb}) { $continue = $self->_callback($c, $cb, $last) }
  else { $continue = $self->_controller($c, $field, $last) }
  $match->current($current);

  # Break the chain
  return undef if !$last && !$continue;

  # Continue
  return $self->continue($c);
}

sub dispatch {
  my ($self, $c) = @_;

  # Path (partial path gets priority)
  my $req  = $c->req;
  my $path = $c->stash->{path};
  if (defined $path) { $path = "/$path" if $path !~ m!^/! }
  else               { $path = $req->url->path->to_route }

  # Method (HEAD will be treated as GET)
  my $method = uc $req->method;
  $method = 'GET' if $method eq 'HEAD';

  # Check cache
  my $cache = $self->cache;
  my $ws    = $c->tx->is_websocket ? 1 : 0;
  my $match = Mojolicious::Routes::Match->new(root => $self);
  $c->match($match);
  if ($cache && (my $cached = $cache->get("$method:$path:$ws"))) {
    $match->endpoint($cached->{endpoint})->stack($cached->{stack});
  }

  # Check routes
  else {
    my $options = {method => $method, path => $path, websocket => $ws};
    $match->match($c => $options);

    # Cache routes without conditions
    if ($cache && (my $endpoint = $match->endpoint)) {
      my $result = {endpoint => $endpoint, stack => $match->stack};
      $cache->set("$method:$path:$ws" => $result)
        unless $endpoint->has_conditions;
    }
  }

  return undef unless @{$c->match->stack};
  $self->auto_render($c) if $self->continue($c);
  return 1;
}

sub hide { push @{shift->hidden}, @_ }

sub is_hidden {
  my ($self, $method) = @_;
  my $h = $self->{hiding} ||= {map { $_ => 1 } @{$self->hidden}};
  return !!($h->{$method} || index($method, '_') == 0 || $method !~ /[a-z]/);
}

sub lookup {
  my ($self, $name) = @_;
  my $reverse = $self->{reverse} ||= {};
  return $reverse->{$name} if exists $reverse->{$name};
  return undef unless my $route = $self->find($name);
  return $reverse->{$name} = $route;
}

sub route {
  shift->add_child(Mojolicious::Routes::Route->new(@_))->children->[-1];
}

sub _action { shift->plugins->emit_chain(around_action => @_) }

sub _add {
  my ($self, $attr, $name, $cb) = @_;
  $self->$attr->{$name} = $cb;
  return $self;
}

sub _callback {
  my ($self, $c, $cb, $last) = @_;
  $c->stash->{'mojo.routed'}++ if $last;
  my $app = $c->app;
  $app->log->debug('Routing to a callback.');
  return _action($app, $c, $cb, $last);
}

sub _class {
  my ($self, $c, $field) = @_;

  # Application instance
  return $field->{app} if ref $field->{app};

  # Application class
  my @classes;
  my $class = $field->{controller} ? camelize($field->{controller}) : '';
  if ($field->{app}) { push @classes, $field->{app} }

  # Specific namespace
  elsif (defined(my $namespace = $field->{namespace})) {
    if ($class) { push @classes, $namespace ? "${namespace}::$class" : $class }
    elsif ($namespace) { push @classes, $namespace }
  }

  # All namespaces
{'fraction_non_alphanumeric': 0.2217687074829932, 'fraction_numerical': 0.0017316017316017316, 'mean_word_length': 3.6232132647226987, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 188, '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': '2195358', 'n_tokens_mistral': 3042, 'n_tokens_neox': 2967, 'n_words': 722}