From afeede01e4b2d076878c6d27ff6ed3372c680061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n?= Date: Mon, 9 Sep 2019 13:12:26 -0700 Subject: [PATCH] fix stringify_typehint() bugs (#35) ...mostly by delegating to the new ScannedTypehint::getTypeText(), but also a few other fixes, e.g. a few places were calling stringify_typehint() incorrectly. This is the diff when running on itself: https://gist.github.com/jjergus/bcf87815d8ca29f661c60dc02be4f396 (all changes are good) --- .travis.yml | 2 +- composer.json | 2 +- src/PageSections/InterfaceSynopsis.hack | 8 ++-- src/PageSections/TypeDeclaration.hack | 23 ++++++---- .../_Private/AUTO_IMPORT_TYPES.hack | 43 ------------------- .../_Private/ns_normalize_type.hack | 33 -------------- .../_Private/stringify_generic.hack | 7 ++- .../_Private/stringify_typehint.hack | 29 ++++--------- 8 files changed, 34 insertions(+), 113 deletions(-) delete mode 100644 src/PageSections/_Private/AUTO_IMPORT_TYPES.hack delete mode 100644 src/PageSections/_Private/ns_normalize_type.hack diff --git a/.travis.yml b/.travis.yml index 53abfb7..bca6f47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ sudo: required language: generic services: docker env: -- HHVM_VERSION=4.14-latest +- HHVM_VERSION=4.21-latest - HHVM_VERSION=latest - HHVM_VERSION=nightly install: diff --git a/composer.json b/composer.json index 0b91831..52513eb 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "hhvm/hsl": "^4.0", "facebook/fbmarkdown": "^1.0", "facebook/hh-clilib": "^2.1.0", - "facebook/definition-finder": "^2.0.0", + "facebook/definition-finder": "^2.12.3", "hhvm/hhast": "^4.14" }, "require-dev": { diff --git a/src/PageSections/InterfaceSynopsis.hack b/src/PageSections/InterfaceSynopsis.hack index 23f8a4d..4f760f7 100644 --- a/src/PageSections/InterfaceSynopsis.hack +++ b/src/PageSections/InterfaceSynopsis.hack @@ -143,13 +143,13 @@ final class InterfaceSynopsis extends PageSection { $ret .= $c->getShortName(); - $p = $c->getParentClassName(); + $p = $c->getParentClassInfo(); if ($p !== null) { - $ret .= ' extends '._Private\ns_normalize_type($ns, $p); + $ret .= ' extends '._Private\stringify_typehint($ns, $p); } - if ($interfaces = $c->getInterfaceNames()) { + if ($interfaces = $c->getInterfaceInfo()) { $ret .= $interfaces - |> Vec\map($$, $i ==> _Private\ns_normalize_type($ns, $i)) + |> Vec\map($$, $i ==> _Private\stringify_typehint($ns, $i)) |> Str\join($$, ', ') |> ' implements '.$$; } diff --git a/src/PageSections/TypeDeclaration.hack b/src/PageSections/TypeDeclaration.hack index 70155f6..7d2873b 100644 --- a/src/PageSections/TypeDeclaration.hack +++ b/src/PageSections/TypeDeclaration.hack @@ -40,19 +40,24 @@ final class TypeDeclaration extends PageSection { $code .= 'newtype '; } - $code .= _Private\ns_normalize_type($ns, $t->getName()); + $code .= $t->getShortName(); if ($t is ScannedType) { - $code .= ' = '. - _Private\stringify_typehint( - $t->getNamespaceName(), - $t->getAliasedType(), - ). - ';'; - } else { - $code .= ';'; + $code .= ' = '; + // We want custom multi-line formatting for shapes here, so not calling + // stringify_typehint() for those. Note that we still use the default + // stringify_typehint() for shapes in other places, e.g. as function + // arguments. + $code .= $t->getAliasedType()->isShape() + ? _Private\stringify_shape($ns, $t->getAliasedType()->getShapeFields()) + : _Private\stringify_typehint( + $t->getNamespaceName(), + $t->getAliasedType(), + ); } + $code .= ';'; + return Str\format("```Hack\n%s\n```", $code); } } diff --git a/src/PageSections/_Private/AUTO_IMPORT_TYPES.hack b/src/PageSections/_Private/AUTO_IMPORT_TYPES.hack deleted file mode 100644 index b9b7937..0000000 --- a/src/PageSections/_Private/AUTO_IMPORT_TYPES.hack +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -namespace Facebook\HHAPIDoc\PageSections\_Private; - -const keyset AUTO_IMPORT_TYPES = keyset[ - 'string', - 'int', - 'float', - 'num', - 'bool', - 'vec', - 'dict', - 'keyset', - 'Awaitable', - 'Vector', - 'Map', - 'Set', - 'ImmVector', - 'ImmMap', - 'ImmSet', - 'Traversable', - 'KeyedTraversable', - 'Container', - 'KeyedContainer', - 'Iterator', - 'KeyedIterator', - 'Iterable', - 'KeyedIterable', - 'Collection', - 'KeyedCollection', - 'IMemoizeParam', - 'AsyncIterator', - 'AsyncGenerator', - 'TypeStructure', - 'shape', -]; diff --git a/src/PageSections/_Private/ns_normalize_type.hack b/src/PageSections/_Private/ns_normalize_type.hack deleted file mode 100644 index 3fb8f31..0000000 --- a/src/PageSections/_Private/ns_normalize_type.hack +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2018-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -namespace Facebook\HHAPIDoc\PageSections\_Private; - -use namespace HH\Lib\{C, Str}; - -/** Render `$type` as concisely and unambiguously as possible in the current - * namespace */ -function ns_normalize_type( - string $ns, - string $type, -): string { - if ($ns === '') { - return $type; - } - - if (C\contains_key(AUTO_IMPORT_TYPES, $type)) { - return $type; - } - - $ns .= "\\"; - if (Str\starts_with($type, $ns)) { - return Str\strip_prefix($type, $ns); - } - return "\\".$type; -} diff --git a/src/PageSections/_Private/stringify_generic.hack b/src/PageSections/_Private/stringify_generic.hack index 2bed916..431ec00 100644 --- a/src/PageSections/_Private/stringify_generic.hack +++ b/src/PageSections/_Private/stringify_generic.hack @@ -23,7 +23,7 @@ function stringify_generic( } else { $base = ''; } - $base .= ns_normalize_type($ns, $generic->getName()); + $base .= $generic->getName(); $constraints = $generic->getConstraints(); if (C\is_empty($constraints)) { @@ -31,7 +31,10 @@ function stringify_generic( } return $constraints - |> Vec\map($$, $c ==> $c['relationship'].' '.$c['type']->getTypeText()) + |> Vec\map( + $$, + $c ==> $c['relationship'].' '.stringify_typehint($ns, $c['type']), + ) |> Str\join($$, ' ') |> $base.' '.$$; } diff --git a/src/PageSections/_Private/stringify_typehint.hack b/src/PageSections/_Private/stringify_typehint.hack index 1712dcc..5f06518 100644 --- a/src/PageSections/_Private/stringify_typehint.hack +++ b/src/PageSections/_Private/stringify_typehint.hack @@ -9,29 +9,18 @@ namespace Facebook\HHAPIDoc\PageSections\_Private; -use type Facebook\DefinitionFinder\ScannedTypehint; -use namespace HH\Lib\{C, Str, Vec}; +use type Facebook\DefinitionFinder\{ScannedTypehint, TypeTextOptions}; +/** + * Render `$type` as concisely and unambiguously as possible in the current + * namespace. + */ function stringify_typehint( string $ns, ScannedTypehint $type, ): string { - $s = $type->isNullable() ? '?' : ''; - if ($type->isShape()) { - return $s.stringify_shape($ns, $type->getShapeFields()); - } - invariant($type->getTypeName() !== 'shape', 'got a shape thats not a shape'); - $s .= ns_normalize_type($ns, $type->getTypeName()); - - $generics = $type->getGenericTypes(); - if (C\is_empty($generics)) { - return $s; - } - - $s .= $generics - |> Vec\map($$, $sub ==> stringify_typehint($ns, $sub)) - |> Str\join($$, ', ') - |> '<'.$$.'>'; - - return $s; + // This just delegates to the implementation in ScannedTypehint, but we keep + // this function here to ensure that we always call getTypeText() consistently + // with the same options. + return $type->getTypeText($ns, TypeTextOptions::STRIP_AUTOIMPORTED_NAMESPACE); }