file->getFilePath(); if ($this->skipper->shouldSkipElementAndFilePath(self::class, $filePath)) { return null; } $newStmts = $this->file->getNewStmts(); if ($newStmts === []) { return null; } $rootStmt = \current($newStmts); $stmt = $rootStmt; if ($rootStmt instanceof FileWithoutNamespace) { $currentStmt = \current($rootStmt->stmts); if (!$currentStmt instanceof Stmt) { return null; } $nodes = $rootStmt->stmts; $stmt = $currentStmt; } if (!$stmt instanceof Stmt) { return null; } if ($this->shouldSkip($stmt)) { return null; } $declareDeclare = new DeclareDeclare(new Identifier('strict_types'), new LNumber(1)); $strictTypesDeclare = new Declare_([$declareDeclare]); $rectorWithLineChange = new RectorWithLineChange(self::class, $stmt->getLine()); $this->file->addRectorClassWithLine($rectorWithLineChange); if ($rootStmt instanceof FileWithoutNamespace) { /** @var Stmt[] $nodes */ $rootStmt->stmts = \array_merge([$strictTypesDeclare, new Nop()], $nodes); return [$rootStmt]; } return \array_merge([$strictTypesDeclare, new Nop()], $nodes); } /** * @return array> */ public function getNodeTypes() : array { return [StmtsAwareInterface::class]; } /** * @param StmtsAwareInterface $node */ public function refactor(Node $node) : ?Node { // workaroudn, as Rector now only hooks to specific nodes, not arrays return null; } private function shouldSkip(Stmt $stmt) : bool { // when first stmt is Declare_, verify if there is strict_types definition already, // as multiple declare is allowed, with declare(strict_types=1) only allowed on very first stmt if ($stmt instanceof Declare_) { foreach ($stmt->declares as $declare) { if ($declare->key->toString() === 'strict_types') { return \true; } } } return \false; } }