From a169f3b1064dde987fb89d135d4855d946e9aeea Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Thu, 14 Jan 2016 00:55:00 +0000 Subject: [PATCH 1/2] Support setting and using namespaces --- src/CodegenFile.php | 33 ++++++++++++++++++++++++++++++++ test/CodegenFileTestCase.codegen | 17 ++++++++++++++++ test/CodegenFileTestCase.php | 15 +++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/CodegenFile.php b/src/CodegenFile.php index 6f6ae246..bc282457 100644 --- a/src/CodegenFile.php +++ b/src/CodegenFile.php @@ -39,6 +39,8 @@ final class CodegenFile { private ?Map> $rekey = null; private bool $createOnly = false; private ?ICodegenFormatter $formatter; + private ?string $fileNamespace; + private Vector $useNamespaces = Vector {}; public function __construct( private IHackCodegenConfig $config, @@ -270,6 +272,13 @@ public function setDoClobber(bool $do_force): this { private function getContent(): string { $builder = hack_builder(); + $builder->addLineIf( + $this->fileNamespace !== null, + 'namespace %s;', + $this->fileNamespace, + ); + $builder->addLines($this->useNamespaces); + foreach ($this->beforeTypes as $type) { $builder->ensureNewLine()->newLine(); $builder->add($type->render()); @@ -330,6 +339,30 @@ public function setGeneratedFrom( return $this; } + public function setNamespace(string $file_namespace): this { + $this->fileNamespace = $file_namespace; + return $this; + } + + public function useNamespace(string $ns, ?string $as = null): this { + $this->useNamespaces[] = $as === null + ? "use $ns;" + : "use $ns as $as;"; + return $this; + } + + public function useClass(string $ns, ?string $as = null): this { + return $this->useNamespace($ns, $as); + } + + public function useFunction(string $ns, ?string $as = null): this { + return $this->useNamespace('function '.$ns, $as); + } + + public function useConst(string $ns, ?string $as = null): this { + return $this->useNamespace('const '.$ns, $as); + } + /** * If called, save() will only write the file if it doesn't exist */ diff --git a/test/CodegenFileTestCase.codegen b/test/CodegenFileTestCase.codegen index 700d5143..58dea2c4 100644 --- a/test/CodegenFileTestCase.codegen +++ b/test/CodegenFileTestCase.codegen @@ -30,6 +30,23 @@ function fun(): int { return 0; } +!@#$%codegentest:testNamespace +> + */ +namespace MyNamespace; +use Another\Space; +use My\Space\Bar as bar; +use function My\Space\my_function as f; +use const My\Space\MAX_RETRIES; + +class Foo { +} + !@#$%codegentest:testNoSignature setNamespace('MyNamespace') + ->useNamespace('Another\Space') + ->useClass('My\Space\Bar', 'bar') + ->useFunction('My\Space\my_function', 'f') + ->useConst('My\Space\MAX_RETRIES') + ->addClass( + codegen_class('Foo') + ) + ->render(); + + self::assertUnchanged($code); + } + } From 9a5db6ec683291d0084586bec4192057a611ff96 Mon Sep 17 00:00:00 2001 From: Gaurav Kumar Date: Thu, 14 Jan 2016 00:55:00 +0000 Subject: [PATCH 2/2] Support setting and using namespaces --- src/CodegenFile.php | 39 ++++++++++++++++++++++++++++++++ test/CodegenFileTestCase.codegen | 17 ++++++++++++++ test/CodegenFileTestCase.php | 15 ++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/CodegenFile.php b/src/CodegenFile.php index 6f6ae246..d28ec034 100644 --- a/src/CodegenFile.php +++ b/src/CodegenFile.php @@ -39,6 +39,8 @@ final class CodegenFile { private ?Map> $rekey = null; private bool $createOnly = false; private ?ICodegenFormatter $formatter; + private ?string $fileNamespace; + private Map $useNamespaces = Map {}; public function __construct( private IHackCodegenConfig $config, @@ -270,6 +272,16 @@ public function setDoClobber(bool $do_force): this { private function getContent(): string { $builder = hack_builder(); + $builder->addLineIf( + $this->fileNamespace !== null, + 'namespace %s;', + $this->fileNamespace, + ); + + foreach ($this->useNamespaces as $ns => $as) { + $builder->addLine($as === null ? "use $ns;" : "use $ns as $as;"); + } + foreach ($this->beforeTypes as $type) { $builder->ensureNewLine()->newLine(); $builder->add($type->render()); @@ -330,6 +342,33 @@ public function setGeneratedFrom( return $this; } + public function setNamespace(string $file_namespace): this { + invariant($this->fileNamespace === null, 'namespace has already been set'); + $this->fileNamespace = $file_namespace; + return $this; + } + + public function useNamespace(string $ns, ?string $as = null): this { + invariant( + !$this->useNamespaces->contains($ns), + $ns.' is already being used', + ); + $this->useNamespaces[$ns] = $as; + return $this; + } + + public function useClass(string $ns, ?string $as = null): this { + return $this->useNamespace($ns, $as); + } + + public function useFunction(string $ns, ?string $as = null): this { + return $this->useNamespace('function '.$ns, $as); + } + + public function useConst(string $ns, ?string $as = null): this { + return $this->useNamespace('const '.$ns, $as); + } + /** * If called, save() will only write the file if it doesn't exist */ diff --git a/test/CodegenFileTestCase.codegen b/test/CodegenFileTestCase.codegen index 700d5143..58dea2c4 100644 --- a/test/CodegenFileTestCase.codegen +++ b/test/CodegenFileTestCase.codegen @@ -30,6 +30,23 @@ function fun(): int { return 0; } +!@#$%codegentest:testNamespace +> + */ +namespace MyNamespace; +use Another\Space; +use My\Space\Bar as bar; +use function My\Space\my_function as f; +use const My\Space\MAX_RETRIES; + +class Foo { +} + !@#$%codegentest:testNoSignature setNamespace('MyNamespace') + ->useNamespace('Another\Space') + ->useClass('My\Space\Bar', 'bar') + ->useFunction('My\Space\my_function', 'f') + ->useConst('My\Space\MAX_RETRIES') + ->addClass( + codegen_class('Foo') + ) + ->render(); + + self::assertUnchanged($code); + } + }