diff --git a/src/languages/php.js b/src/languages/php.js
index a23b6543c2..c695705c00 100644
--- a/src/languages/php.js
+++ b/src/languages/php.js
@@ -12,10 +12,13 @@ Category: common
* */
export default function(hljs) {
const regex = hljs.regex;
- const IDENT_RE = '([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' +
+ const IDENT_RE_CORE = '[a-zA-Z0-9_\x7f-\xff]*' +
// negative look-ahead tries to avoid matching patterns that are not
// Perl at all like $ident$, @ident@, etc.
'(?![A-Za-z0-9])(?![$]))';
+ const IDENT_RE = regex.concat("([a-zA-Z_\\x7f-\\xff]", IDENT_RE_CORE);
+ // Will not detect camelCase classes
+ const PASCAL_CASE_CLASS_NAME_RE = regex.concat("([A-Z]", IDENT_RE_CORE);
const VARIABLE = {
scope: 'variable',
match: '\\$+' + IDENT_RE,
@@ -47,7 +50,7 @@ export default function(hljs) {
end: /[ \t]*(\w+)\b/,
contains: hljs.QUOTE_STRING_MODE.contains.concat(SUBST),
});
- // list of valid whitespaces because non-breaking space might be part of a name
+ // list of valid whitespaces because non-breaking space might be part of a IDENT_RE
const WHITESPACE = '[ \t\n]';
const STRING = {
scope: 'string',
@@ -331,7 +334,7 @@ export default function(hljs) {
/\b/,
// to prevent keywords from being confused as the function title
regex.concat("(?!fn\\b|function\\b|", normalizeKeywords(KWS).join("\\b|"), "|", normalizeKeywords(BUILT_INS).join("\\b|"), "\\b)"),
- regex.concat(IDENT_RE, "+"),
+ IDENT_RE,
regex.concat(WHITESPACE, "*"),
regex.lookahead(/(?=\()/)
],
@@ -340,6 +343,57 @@ export default function(hljs) {
}
};
+ const CONSTANT_REFERENCE = regex.concat(IDENT_RE, "\\b(?!\\()");
+
+ const LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON = {
+ variants: [
+ {
+ match: [
+ regex.concat(
+ /::/,
+ regex.lookahead(/(?!class\b)/)
+ ),
+ CONSTANT_REFERENCE,
+ ],
+ scope: {
+ 2: "variable.constant",
+ },
+ },
+ {
+ match: [
+ /::/,
+ /class/,
+ ],
+ scope: {
+ 2: "variable.language",
+ },
+ },
+ {
+ match: [
+ PASCAL_CASE_CLASS_NAME_RE,
+ regex.concat(
+ "::",
+ regex.lookahead(/(?!class\b)/)
+ ),
+ ],
+ scope: {
+ 1: "title.class",
+ },
+ },
+ {
+ match: [
+ PASCAL_CASE_CLASS_NAME_RE,
+ /::/,
+ /class/,
+ ],
+ scope: {
+ 1: "title.class",
+ 3: "variable.language",
+ },
+ }
+ ]
+ };
+
return {
case_insensitive: false,
keywords: KEYWORDS,
@@ -380,16 +434,17 @@ export default function(hljs) {
},
VARIABLE,
FUNCTION_INVOKE,
+ LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON,
{
match: [
/const/,
- regex.concat(WHITESPACE, "+"),
+ /\s/,
IDENT_RE,
- regex.concat(WHITESPACE, "*="),
+ /\s*=/,
],
scope: {
1: "keyword",
- 3: "variable",
+ 3: "variable.constant",
},
},
{
@@ -425,6 +480,7 @@ export default function(hljs) {
contains: [
'self',
VARIABLE,
+ LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON,
hljs.C_BLOCK_COMMENT_MODE,
STRING,
NUMBER
diff --git a/test/markup/php/functions.expect.txt b/test/markup/php/functions.expect.txt
index f6bc43f49a..88c5d94ebe 100644
--- a/test/markup/php/functions.expect.txt
+++ b/test/markup/php/functions.expect.txt
@@ -13,7 +13,7 @@
$date = new DateTimeImmutable ();
$date->format('Y-m-d');
-DateTimeImmutable::createFromMutable(new \DateTime('now'));
+DateTimeImmutable::createFromMutable(new \DateTime('now'));
str_contains (\strtoupper(substr('abcdef', -2), 'f'));
diff --git a/test/markup/php/titles.expect.txt b/test/markup/php/titles.expect.txt
index 03a9daaf19..05763d78a2 100644
--- a/test/markup/php/titles.expect.txt
+++ b/test/markup/php/titles.expect.txt
@@ -1,8 +1,8 @@
-final class Example {
- const FOO='foo';
+final class Example extends Foo {
+ const FOO='foo';
public function __construct(
- public readonly string $name = self::FOO
+ public readonly string $name = self::FOO
) {}
public function getClass(): string {
@@ -16,7 +16,11 @@
public static function getClassFromStatic(): string {
return static::class;
}
+
+ public static function getParentClass(): string {
+ return parent::class;
+ }
}
-$date = DateTimeImmutable::createFromMutable(new \DateTime());
+$date = DateTimeImmutable::createFromMutable(new \DateTime());
echo $date::class;
diff --git a/test/markup/php/titles.txt b/test/markup/php/titles.txt
index ffa405fb72..6ff19f2fc6 100644
--- a/test/markup/php/titles.txt
+++ b/test/markup/php/titles.txt
@@ -1,4 +1,4 @@
-final class Example {
+final class Example extends Foo {
const FOO='foo';
public function __construct(
@@ -16,6 +16,10 @@ final class Example {
public static function getClassFromStatic(): string {
return static::class;
}
+
+ public static function getParentClass(): string {
+ return parent::class;
+ }
}
$date = DateTimeImmutable::createFromMutable(new \DateTime());