aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--queries/hack/highlights.scm142
-rw-r--r--tests/query/highlights/hack/as-foreach.hack6
-rw-r--r--tests/query/highlights/hack/async-functions.hack8
-rw-r--r--tests/query/highlights/hack/attribute-type.hack15
-rw-r--r--tests/query/highlights/hack/generics.hack23
-rw-r--r--tests/query/highlights/hack/heredoc-dollar.hack4
-rw-r--r--tests/query/highlights/hack/use.hack28
-rw-r--r--tests/query/highlights/hack/using.hack3
-rw-r--r--tests/query/highlights/hack/xhp.hack10
-rw-r--r--tests/query/highlights/xhp-intro.hack46
10 files changed, 280 insertions, 5 deletions
diff --git a/queries/hack/highlights.scm b/queries/hack/highlights.scm
index 29139aaff..1bde66632 100644
--- a/queries/hack/highlights.scm
+++ b/queries/hack/highlights.scm
@@ -1,4 +1,16 @@
+(variable) @variable
+(identifier) @variable
+((variable) @variable.builtin
+ (#eq? @variable.builtin "$this"))
+
+(braced_expression) @none
+
+(scoped_identifier
+ (qualified_identifier
+ (identifier) @type))
+
(comment) @comment
+(heredoc) @comment
[
"function"
@@ -10,14 +22,28 @@
"type"
"interface"
"class"
+ "protected"
+ "private"
+ "public"
+ "using"
+ "namespace"
+ "attribute"
+ "const"
+ (xhp_modifier)
+ (final_modifier)
+ "extends"
+ "insteadof"
] @keyword
+"use" @include
+
[
"new"
"print"
"echo"
"newtype"
"clone"
+ "as"
] @keyword.operator
[
@@ -39,10 +65,30 @@
"mixed"
"dynamic"
"noreturn"
-] @type
+] @type.builtin
+
+(type_specifier) @type
+(new_expression
+ (_) @type)
+
+(alias_declaration "newtype" . (_) @type)
+(alias_declaration "type" . (_) @type)
+
+(class_declaration
+ name: (identifier) @type)
+(type_parameter
+ name: (identifier) @type)
-(type_specifier
- (qualified_identifier) @type)
+(collection
+ (qualified_identifier
+ (identifier) @type .))
+
+(function_type_specifier) @function
+(attribute_modifier) @attribute
+[
+ "@required"
+ "@lateinit"
+] @attribute
[
"="
@@ -79,6 +125,7 @@
"<=>"
"<<"
">>"
+ "->"
"+"
"-"
"."
@@ -107,6 +154,7 @@
"/="
"%="
"**="
+ "=>"
;; type modifiers
"@"
@@ -121,15 +169,90 @@
(variable) @parameter)
(call_expression
- function: (qualified_identifier) @function)
+ function: (qualified_identifier (identifier) @function .))
+
+(call_expression
+ function: (scoped_identifier (identifier) @function .))
+
+(call_expression
+ function: (selection_expression
+ (qualified_identifier (identifier) @method .)))
+
+(qualified_identifier
+ (_) @namespace .
+ (_))
+
+(use_statement
+ (qualified_identifier
+ (_) @namespace .)
+ (use_clause))
+
+(use_statement
+ (use_type "namespace")
+ (use_clause
+ (qualified_identifier
+ (identifier) @namespace .)
+ alias: (identifier)? @namespace))
+
+(use_statement
+ (use_type "const")
+ (use_clause
+ (qualified_identifier
+ (identifier) @constant .)
+ alias: (identifier)? @constant))
+
+(use_statement
+ (use_type "function")
+ (use_clause
+ (qualified_identifier
+ (identifier) @function .)
+ alias: (identifier)? @function))
+
+(use_statement
+ (use_type "type")
+ (use_clause
+ (qualified_identifier
+ (identifier) @type .)
+ alias: (identifier)? @type))
+
+(use_clause
+ (use_type "namespace")
+ (qualified_identifier
+ (_) @namespace .)
+ alias: (identifier)? @namespace)
+
+(use_clause
+ (use_type "function")
+ (qualified_identifier
+ (_) @function .)
+ alias: (identifier)? @function)
+
+(use_clause
+ (use_type "const")
+ (qualified_identifier
+ (_) @constant .)
+ alias: (identifier)? @constant)
+
+(use_clause
+ (use_type "type")
+ (qualified_identifier
+ (_) @type .)
+ alias: (identifier)? @type)
(function_declaration
name: (identifier) @function)
+(method_declaration
+ name: (identifier) @method)
(type_arguments
[ "<" ">" ] @punctuation.bracket)
[ "(" ")" "[" "]" "{" "}" "<<" ">>"] @punctuation.bracket
+(xhp_open
+ [ "<" ">" ] @tag.delimiter)
+(xhp_close
+ [ "</" ">" ] @tag.delimiter)
+
[ "." ";" "::" ":" "," ] @punctuation.delimiter
(ternary_expression
@@ -152,11 +275,20 @@
[
"for"
"while"
+ "foreach"
"do"
"continue"
"break"
] @repeat
-(string) @string
+[
+ (string)
+ (xhp_string)
+] @string
+
+[
+ (xhp_open)
+ (xhp_close)
+] @tag
(ERROR) @error
diff --git a/tests/query/highlights/hack/as-foreach.hack b/tests/query/highlights/hack/as-foreach.hack
new file mode 100644
index 000000000..8969be8fc
--- /dev/null
+++ b/tests/query/highlights/hack/as-foreach.hack
@@ -0,0 +1,6 @@
+foreach (($array as vec[]) as $item) {}
+// ^ repeat
+// ^ type
+
+# Our expectation test for the code below intentionally includes an ERROR.
+foreach ($array as vec[] as $item) {}
diff --git a/tests/query/highlights/hack/async-functions.hack b/tests/query/highlights/hack/async-functions.hack
new file mode 100644
index 000000000..4488c992d
--- /dev/null
+++ b/tests/query/highlights/hack/async-functions.hack
@@ -0,0 +1,8 @@
+async function func0(): void {}
+// ^ type.builtin
+async function func1<T1 as int>() {}
+// ^ type.builtin
+// ^ keyword.operator
+
+
+async ($x) ==> $x + 1;
diff --git a/tests/query/highlights/hack/attribute-type.hack b/tests/query/highlights/hack/attribute-type.hack
new file mode 100644
index 000000000..9f62d19df
--- /dev/null
+++ b/tests/query/highlights/hack/attribute-type.hack
@@ -0,0 +1,15 @@
+<<A1>>
+newtype T1 = ?shape(
+// TODO: ?operator (? not captureable at the moment)
+ ?'int' => int
+// ^ operator
+);
+
+<<A3(1), A2(2,3,)>>
+// ^ attribute
+type T2 = (function(T1): string);
+// ^ type
+// ^ function (cannot capture keyword "function" as keyword.function)
+
+<<A4(1), A5, A6(1,3,4)>>
+newtype T3 as int = int;
diff --git a/tests/query/highlights/hack/generics.hack b/tests/query/highlights/hack/generics.hack
new file mode 100644
index 000000000..ea605420c
--- /dev/null
+++ b/tests/query/highlights/hack/generics.hack
@@ -0,0 +1,23 @@
+class Box<T> {
+ // ^ type
+ // ^ type
+ protected T $data;
+ // ^ keyword
+ // ^ type
+
+ public function __construct(T $data) {
+ // ^ type
+ // ^ parameter
+ // ^ keyword
+ // ^ method
+ $this->data = $data;
+ }
+
+ public function getData(): T {
+ // ^ method
+ // ^ keyword
+ return $this->data;
+ // ^ operator
+ // ^ variable.builtin
+ }
+}
diff --git a/tests/query/highlights/hack/heredoc-dollar.hack b/tests/query/highlights/hack/heredoc-dollar.hack
new file mode 100644
index 000000000..8034cc863
--- /dev/null
+++ b/tests/query/highlights/hack/heredoc-dollar.hack
@@ -0,0 +1,4 @@
+<<<EOT
+ $('a') abc $(function{return;})
+EOT;
+// <- comment ^ comment
diff --git a/tests/query/highlights/hack/use.hack b/tests/query/highlights/hack/use.hack
new file mode 100644
index 000000000..d7b7ce784
--- /dev/null
+++ b/tests/query/highlights/hack/use.hack
@@ -0,0 +1,28 @@
+use const Space\Const\C;
+// ^ keyword
+// ^ constant
+use function Space\Func\F as E;
+// ^ function
+// ^ function
+use type Space\Type\T;
+// ^ keyword
+use namespace Space\Name\N as M;
+// ^ keyword
+// ^ namespace
+
+use namespace Space\Name2\N2, Space\Nothing\N3 as N8, type Space\Type2\N4,;
+// ^ namespace
+// ^ type
+use namespace Space\Name\N10\{A as A2, B\};
+// ^ namespace
+// ^ namespace
+// ^ namespace
+use namespace Space\Name\{\C, Slash as Forward};
+
+use \What\Is\This\{function A as A2, B, const H\S\L as stdlib, function F};
+
+use type \{kind,};
+use Q\B\{kind2,};
+// ^ namespace
+use type Q\B\{kind3,};
+// <- include
diff --git a/tests/query/highlights/hack/using.hack b/tests/query/highlights/hack/using.hack
new file mode 100644
index 000000000..4452ea962
--- /dev/null
+++ b/tests/query/highlights/hack/using.hack
@@ -0,0 +1,3 @@
+using ($new = new Object(), $file = new File('using', '+using')) {}
+// <- keyword
+// ^ type
diff --git a/tests/query/highlights/hack/xhp.hack b/tests/query/highlights/hack/xhp.hack
new file mode 100644
index 000000000..992296b97
--- /dev/null
+++ b/tests/query/highlights/hack/xhp.hack
@@ -0,0 +1,10 @@
+$user_name = 'Fred';
+echo "<tt>Hello <strong>$user_name</tt></strong>";
+
+// XHP: Typechecked, well-formed, and secure
+$user_name = 'Andrew';
+$xhp = <tt>Hello <strong>{$user_name}</strong></tt>;
+// ^ tag
+// ^ tag
+// ^ string
+echo await $xhp->toStringAsync();
diff --git a/tests/query/highlights/xhp-intro.hack b/tests/query/highlights/xhp-intro.hack
new file mode 100644
index 000000000..cc25f5843
--- /dev/null
+++ b/tests/query/highlights/xhp-intro.hack
@@ -0,0 +1,46 @@
+// From https://docs.hhvm.com/hack/XHP/introduction (MIT licensed)
+
+use namespace Facebook\XHP\Core as x;
+use type Facebook\XHP\HTML\{XHPHTMLHelpers, a, form};
+
+
+final xhp class a_post extends x\element {
+// ^ keyword
+// ^ keyword
+// ^ keyword
+ use XHPHTMLHelpers;
+
+ attribute string href @required;
+ // ^ attribute
+ attribute string target;
+ // ^ keyword
+
+ <<__Override>>
+ protected async function renderAsync(): Awaitable<x\node> {
+ $id = $this->getID();
+
+ $anchor = <a>{$this->getChildren()}</a>;
+ // ^ tag.delimiter
+ // ^ tag
+ $form = (
+ <form
+ id={$id}
+ method="post"
+ action={$this->:href}
+ target={$this->:target}
+ class="postLink">
+ {$anchor}
+ </form>
+ );
+
+ $anchor->setAttribute(
+ 'onclick',
+ 'document.getElementById("'.$id.'").submit(); return false;',
+ );
+ $anchor->setAttribute('href', '#');
+ // ^ method
+
+ return $form;
+ }
+}
+