Skip to content

Instantly share code, notes, and snippets.

@fredemmott

fredemmott/examples.hack

Last active Sep 6, 2020
Embed
What would you like to do?
XHP NS 2019-10-22
namespace {
// old: defines '\xhp_foo__bar'
class :foo:bar extends :x:element {}
// new: defines '\foo\bar', extending namespace\x\element which is \x\element
xhp class foo:bar extends x:element {}
// new: equivalent in the root namespace
// defines '\foo\bar', extending \x\element
xhp class foo:bar extends :x:element {}
// parse error: reasonable enough in the root namespace, but not
// in any other namespace. Ban for consistency.
xhp class :foo:bar extends :x:element {}
// new: defines \foo extending \x\element
xhp class foo extends \x\element {}
// new: defines \foo\bar extending \x\element
xhp class foo:bar extends \x\element {}
// old: instantiate \xhp_foo__bar
// new: instantiate namespace\foo\bar, which is \foo\bar
$_ = <foo:bar />;
// old: parse error
// new: instantiate \foo\bar
$_ = <:foo:bar />;
// old and new: instantiates namespace\foo, which is \foo
$_ = <foo />;
// old: parse error
// new: instantiates \foo
$_ = <:foo />;
// old: defines `\xhp_foo__bar_baz'
class :foo:bar-baz {}
// new: parse error
xhp class foo:bar-baz {}
// new: defines \foo\bar_baz
xhp class foo:bar_baz {}
// old: takes a \xhp_foo
// new:
// - takes a \foo
// - type error if \foo is not an XHP type
function dostuff(:foo $_): void {}
// new: takes a namespace\foo, which is a \foo
function dostuff(foo $_): void {}
// old and new: parse error
// - `:` is only permitted in this context if fully-qualified
function dostuff(foo:bar $_): void {}
// parse error - not fully-qualified:
use type foo:bar;
// parse error: not permitted in use statements:
use type :foo:bar;
// parse error:
use type :foo:{bar:baz, bat};
// ^ not permitted in use statements
// ^ fragment is not fully-qualified
// instantiate \foo\bar:
use type foo\bar;
$_ = <bar />;
// error:
use namespace facebook:xhp:html;
// instantiate \facebook\xhp\html\p:
use namespace facebook\xhp\html as h;
$_ = <h:p />;
}
namespace myns {
// old: no usable equivalent
// new: defines '\myns\foo\bar` extending `\x\element`
xhp class foo:bar extends :x:element {}
xhp class foo:bar extends \x\element {}
// new: defines '\myns\foo\bar` extending `\myns\x\element`
// probably a mistake
xhp class foo:bar extends x:element {}
// old: no usable equivalent
// new: parse error: would mean \foo\bar, which is not in \myns\
xhp class :foo:bar {}
// old: uninstantiable but parsable
// new: instantiate namespace\foo\bar, which is myns\foo\bar
$_ = <foo:bar />;
// old: parse error
// new: instantiate \foo\bar
$_ = <:foo:bar />;
// old: no usable equivalent
// new: instantiates namespace\foo, which is myns\foo
$_ = <foo />;
// old: parse error
// new: instantiates \foo
$_ = <:foo />;
// \foo\bar [
// \myns\herp:derp [
// \p [
// "hello"
// ]
// ]
// ]
$_ = <:foo:bar><herp:derp><:p>hello</:p></herp:derp></:foo:bar>;
// old: no usable equivalent
// new:
// - takes a \foo
// - typechecker error if \foo is not an XHP type
function dostuff(:foo $_): void {}
// old and new: parse error
// - `:` is only permitted in this context if fully-qualified
function dostuff(foo:bar $_): void {}
}
// Old and new: file-level attribute bar
<<File:Bar>>
// Old and new: errors. Non-sensical context for XHP types
<<:Foo:Bar>>
<<File::Bar>>
<<NotAFile:Bar>>
<<x:element>>>
<<:x:element>>
new :x:element();

Overview

  • : will become a namespace separator, e.g. foo:bar is equivalent to foo\bar
  • : will no longer become a sigil to indicate XHP classes, as this introduces ambiguities; instead, xhp is introduced as a class modifier, e.g. class :foo becomes xhp class foo
  • names with a leading : are fully-qualified names, e.g. :foo:bar is equivalent to \foo\bar
  • names with a non-leading : are partially-qualified names, e.g. foo:bar is eequivalent to foo\bar
  • fully-qualified names are permitted in XHP constructor calls, e.g. <:foo:bar>
  • the current intent is that : is used for XHP contexts, and \ is used for non-XHP contexts
  • - is banned in XHP class names; this entirely removes name mangling from XHP.

Rules

  • :-qualified names referring to XHP types are permitted:
    • in XHP class decl names
      • e.g. xhp class foo:bar
      • this was origininally intended as a temporary migration aid; it is now considered a feature, to allow codebases to make a stylistic choice to avoid explicit usage of namespaces
      • this is permitted in any namespace
      • MUST NOT be fully qualified e.g. xhp class :foo:bar is a parse error; the intent is to allow XHP classes to be defined in sub-namespaces, but to prevent namespace foo {} containing a definition of \bar\baz
    • in XHP class decl extends lists:
      • e.g. xhp class foo:bar extends x:element
      • MAY be fully qualified
    • in XHP class constructor calls
      • e.g. <foo:bar>, </foo:bar>, <foo:bar /> (partially-qualified)
      • e.g. <:foo:bar>, </:foo:bar>, <:foo:bar /> (fully-qualified)
    • in XHP children declarations:
      • e.g. children (:foo:bar+, herp:derp) (fully-qualified then partially-qualified
    • any other context except for use statements, if fully-qualified; for clarity:
      • : is not permitted in any use statements
      • partially-qualified :-separated-names are not permitted in any contexts except for those explicitly listed previously
  • :-qualified names MUST NOT be permitted for non-XHP types:
    • class foo:bar is an error (as opposed to xhp class foo:bar which is fine)
    • in some contexts (e.g. parameter types, return types) this will need to be a typechecker error, to preserve file-at-a-time parsing
    • in others such as attributes and standard constructor calls (new foo:bar()) , this /could/ be a parse error
  • \ MUST NOT be used for class decl names
    • e.g. class foo\bar and xhp class foo\bar are errors
  • \ MAY be used for XHP class extends lists (xhp class foo extends \x\element)
    • some codebases may want to lint against this
  • \ MAY be used for XHP children declarations (xhp class foo { children (\x\element+) })
  • \ MUST NOT be used for XHP constructor calls
    • e.g. <\foo\bar> is an error

Linter Ideas

  • standardising on either : or \ where both are permitted
  • using : in XHP class declaration names (i.e. ban defining elements in sub-namespaces)
  • mixing : and \ in the same XHP class declaration (e.g. xhp class foo:bar extends \x\element)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.