-
Notifications
You must be signed in to change notification settings - Fork 3.7k
enh(php) Left and right-side of double colon #3422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
c90d127
0e30006
1d9cdf2
2c99563
b13a109
be9c020
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,12 +12,16 @@ Category: common | |
| * */ | ||
| export default function(hljs) { | ||
| const regex = hljs.regex; | ||
| 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: '\\$+[a-zA-Z_\x7f-\xff][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])(?![$])` | ||
| match: '\\$+' + IDENT_RE, | ||
| }; | ||
| const PREPROCESSOR = { | ||
| scope: 'meta', | ||
|
|
@@ -46,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', | ||
|
|
@@ -313,8 +317,8 @@ export default function(hljs) { | |
| regex.concat(WHITESPACE, "+"), | ||
| // to prevent built ins from being confused as the class constructor call | ||
| regex.concat("(?!", normalizeKeywords(BUILT_INS).join("\\b|"), "\\b)"), | ||
| /\\?\w+/, | ||
| regex.concat(WHITESPACE, "*\\("), | ||
| regex.concat(/\\?/, IDENT_RE), | ||
| regex.concat(WHITESPACE, "*", /\(/), | ||
| ], | ||
| scope: { | ||
| 1: "keyword", | ||
|
|
@@ -330,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)"), | ||
| /\w+/, | ||
| IDENT_RE, | ||
| regex.concat(WHITESPACE, "*"), | ||
| regex.lookahead(/(?=\()/) | ||
| ], | ||
|
|
@@ -339,6 +343,57 @@ export default function(hljs) { | |
| } | ||
| }; | ||
|
|
||
| const CONSTANT_REFERENCE = regex.concat(IDENT_RE, "\\b(?!\\()"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is this a constant reference? In other languages our constant rule is ALL_CAPS_CASE. Is anything following a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And if it's truly a constant we'd use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Language allows also lower case or any other, but probably almost all use ALL_CAPS_CASE.
Ok, I guess accessing Enum value is also Constant declaration and Enum values also should be marked with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's that's a "function dispatch" or something, not a "constant"... constant to me means
Perhaps if you could detect they are enum values... I dunno what the PHP syntax is... for most languages it's impossible to do this 100% correctly so we usually have a UPPERCASE constant rule for languages where it's a string pattern and then only catch others in very explicit cases like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I just looked above, yes the enum declarations could be marked that way I suppose... |
||
|
|
||
| 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, | ||
|
|
@@ -351,8 +406,8 @@ export default function(hljs) { | |
| { | ||
| contains: [ | ||
| { | ||
| className: 'doctag', | ||
| begin: '@[A-Za-z]+' | ||
| scope: 'doctag', | ||
| match: '@[A-Za-z]+' | ||
| } | ||
| ] | ||
| } | ||
|
|
@@ -379,12 +434,25 @@ export default function(hljs) { | |
| }, | ||
| VARIABLE, | ||
| FUNCTION_INVOKE, | ||
| LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON, | ||
| { | ||
| match: [ | ||
| /const/, | ||
| /\s/, | ||
| IDENT_RE, | ||
| /\s*=/, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be a look-ahead, I'm not sure why we need to consume it?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I don't know enough about the highlight js to know what's the difference.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we don't just consume things arbitrarily... we aren't highlighting it here, we only need to guarantee it's presence, not consume it. In general we don't consume things we don't need to. Later someone may want to add operator matching where we highlight all |
||
| ], | ||
| scope: { | ||
| 1: "keyword", | ||
| 3: "variable.constant", | ||
| }, | ||
| }, | ||
| { | ||
| // swallow composed identifiers to avoid parsing them as keywords | ||
| match: regex.concat( | ||
| /(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/, | ||
| regex.concat("(?!", WHITESPACE, "*\\()"), | ||
| /(?![a-zA-Z0-9_\x7f-\xff])/ | ||
| /(::|->)+/, | ||
wkania marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| IDENT_RE, | ||
| regex.concat("(?!", WHITESPACE, "*\\()") | ||
|
||
| ), | ||
| // scope:"wrong" | ||
| }, | ||
|
|
@@ -412,6 +480,7 @@ export default function(hljs) { | |
| contains: [ | ||
| 'self', | ||
| VARIABLE, | ||
| LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON, | ||
| hljs.C_BLOCK_COMMENT_MODE, | ||
| STRING, | ||
| NUMBER | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Foo</span> </span>{ | ||
| <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">FOO</span>=<span class="hljs-string">'foo'</span>; | ||
|
|
||
| <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"> | ||
| <span class="hljs-keyword">public</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">string</span> <span class="hljs-variable">$name</span> = <span class="hljs-built_in">self</span>::<span class="hljs-variable constant_">FOO</span> | ||
| </span>) </span>{} | ||
|
|
||
| <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getClass</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{ | ||
| <span class="hljs-keyword">return</span> <span class="hljs-title class_">DateTimeImmutable</span>::<span class="hljs-variable language_">class</span>; | ||
| } | ||
|
|
||
| <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getClassFromSelf</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{ | ||
| <span class="hljs-keyword">return</span> <span class="hljs-built_in">self</span>::<span class="hljs-variable language_">class</span>; | ||
| } | ||
|
|
||
| <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getClassFromStatic</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{ | ||
| <span class="hljs-keyword">return</span> <span class="hljs-built_in">static</span>::<span class="hljs-variable language_">class</span>; | ||
| } | ||
|
|
||
| <span class="hljs-keyword">public</span> <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getParentClass</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{ | ||
| <span class="hljs-keyword">return</span> <span class="hljs-built_in">parent</span>::<span class="hljs-variable language_">class</span>; | ||
| } | ||
| } | ||
|
|
||
| <span class="hljs-variable">$date</span> = <span class="hljs-title class_">DateTimeImmutable</span>::<span class="hljs-title function_ invoke__">createFromMutable</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">\DateTime</span>()); | ||
| <span class="hljs-keyword">echo</span> <span class="hljs-variable">$date</span>::<span class="hljs-variable language_">class</span>; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| final class Example extends Foo { | ||
| const FOO='foo'; | ||
|
|
||
| public function __construct( | ||
| public readonly string $name = self::FOO | ||
| ) {} | ||
|
|
||
| public function getClass(): string { | ||
| return DateTimeImmutable::class; | ||
| } | ||
|
|
||
| public function getClassFromSelf(): string { | ||
| return self::class; | ||
| } | ||
|
|
||
| public static function getClassFromStatic(): string { | ||
| return static::class; | ||
| } | ||
|
|
||
| public static function getParentClass(): string { | ||
| return parent::class; | ||
| } | ||
| } | ||
|
|
||
| $date = DateTimeImmutable::createFromMutable(new \DateTime()); | ||
| echo $date::class; |
Uh oh!
There was an error while loading. Please reload this page.