Skip to content

[detector-report] MutableStaticStateDetector #582

Description

@jessegall

Detector: MutableStaticStateDetector

Report (why the flagged code is CORRECT and the detector is wrong):
Stylesheet::$active is a write-once theme registry set at boot by ViewServiceProvider and read by the primitives' static stylesheet() factories (Text::stylesheet()::token is read in constant expressions and static compose methods, where no instance can be injected); a second write throws ThemeAlreadyChosen, so no writer can win over another and execution order cannot change the answer

Cleanest design the reporter can conceive:
A write-once static registry guarded by a named exception on a second write is the design for a value read from static factories that constant expressions name; an injected instance cannot reach a static compose() or a class-constant expression, and a container lookup inside a primitive would make the Kit fetch

⚖️ Maintainer litmus: a valid detector-report needs the flagged code to ALREADY BE the
cleanest design. If the design above differs from the flagged code at all, THAT design is
the owed fix — close this report; the fix is still owed.

Where: src/View/Stylesheets/Stylesheet.php:24

Code (src/View/Stylesheets/Stylesheet.php:24):

  21              throw ThemeAlreadyChosen::for(array_keys($roles));
  22          }
  2324          self::$active = $roles;
  25      }
  26  
  27      /**
  28       * @template T of PrimitiveRole|CompositionRole
  29       *
  30       * @param  class-string<T>  $role
  31       * @return class-string<T>
  32       */
  33      public static function of(string $role): string
  34      {
  35          return self::$active[$role] ?? $role;
  36      }
  37  }

Where: src/Laravel/ViewServiceProvider.php:95

Code (src/Laravel/ViewServiceProvider.php:95):

   92  
   93      public function register(): void
   94      {
→  95          Stylesheet::use($this->app['config']->get('workflows.theme', []));
   96  
   97          foreach (self::DRIVERS as $contract => $driver)
   98          {
   99              $this->app->scoped($driver);
  100              $this->app->bind($contract, $driver);
  101          }
  102  
  103          $this->app->singleton(CompiledScenes::class, static fn ($app) => new CompiledScenes($app->basePath()));
  104          $this->app->scoped(Shapes::class, static fn ($app) => new Shapes($app->basePath()));
  105          $this->app->singleton(RenderedScenes::class, static fn ($app) => new RenderedScenes($app->basePath()));
  106  
  107          $this->app->scoped(ClientState::class, static fn ($app) => $app->make(Navigation::class)->hasDestination()
  108              ? ClientState::none()
  109              : ClientState::from($app->make(Request::class)));
  110  
  111          $this->app->scoped(Pipes::class);
  112          $this->app->scoped(PipeTimings::class);
  113  
  114          $this->app->scoped(SceneResponse::class, static function ($app) {
  115              $request = $app->make(Request::class);
  116  
  117              return $request->wantsJson() || $request->boolean('json')
  118                  ? $app->make(AsJson::class)
  119                  : $app->make(AsPage::class);

Where: src/View/Primitives/Text.php:25

Code (src/View/Primitives/Text.php:25):

  22       */
  23      public static function stylesheet(): string
  24      {
→ 25          return Stylesheet::of(TextStylesheet::class);
  26      }
  27  
  28      private function __construct(string | StateRef | null $text = null)
  29      {
  30          $this->state->text = $text;
  31      }
  32  
  33      public static function reading(StateRef $ref): self
  34      {
  35          return new self($ref)->passThrough(text: $ref);
  36      }
  37  
  38      public static function of(string | int | null $text = null): self
  39      {
  40          return new self($text === null ? null : (string) $text)->passThrough(text: $text);
  41      }
  42  
  43      public function headingLevel(int $level): static
  44      {
  45          $this->state->headingLevel = $level;
  46  
  47          return $this;
  48      }
  49  }

Filed via commandments report from a consumer project.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions