Skip to content

Commit 0f049d8

Browse files
committed
feat: add documentation provider for opcodes
1 parent a122071 commit 0f049d8

File tree

7 files changed

+97
-22
lines changed

7 files changed

+97
-22
lines changed

src/main/kotlin/com/github/xepozz/php_opcodes_language/language/PHPOpAnnotator.kt

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.xepozz.php_opcodes_language.language
22

3-
import com.github.xepozz.php_opcodes_language.language.psi.PHPOpInstructionName
43
import com.github.xepozz.php_opcodes_language.language.psi.PHPOpParameter
54
import com.github.xepozz.php_opcodes_language.language.psi.PHPOpVarName
65
import com.intellij.lang.annotation.AnnotationHolder
@@ -20,18 +19,9 @@ class PHPOpAnnotator : Annotator {
2019
.create()
2120
}
2221
is PHPOpParameter -> {
23-
if (element.text.matches(Regex("[TV]\\d+"))) {
24-
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
25-
.range(element)
26-
.textAttributes(PhpHighlightingData.VAR)
27-
.create()
28-
}
29-
}
30-
31-
is PHPOpInstructionName -> {
3222
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
3323
.range(element)
34-
.textAttributes(PhpHighlightingData.FUNCTION_CALL)
24+
.textAttributes(if (element.isVariable) PhpHighlightingData.VAR else PhpHighlightingData.FUNCTION_CALL)
3525
.create()
3626
}
3727
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.github.xepozz.php_opcodes_language.language.documentation
2+
3+
/**
4+
* @example https://phpdoctest.github.io/en/internals2.opcodes.list.html
5+
*/
6+
object OpcodesDictionary {
7+
private val directives = listOf(
8+
ParameterDoc(
9+
name = "ADD",
10+
number = 1,
11+
description = """Adds "value1" to "value2" and stores the result into "result"""",
12+
// language=injectablephp
13+
example_php = $$"""
14+
<?php
15+
16+
$a = 1;
17+
$b = 2;
18+
$c = $a + $b;
19+
""".trimIndent(),
20+
// language="PHP Opcodes"
21+
example_opcode = $$"""
22+
$_main:
23+
24+
0000 EXT_STMT
25+
0001 ASSIGN CV0($a) int(1)
26+
0002 EXT_STMT
27+
0003 ASSIGN CV1($b) int(2)
28+
0004 EXT_STMT
29+
0005 T5 = ADD CV0($a) CV1($b)
30+
0006 ASSIGN CV2($c) T5
31+
0007 RETURN int(1)
32+
""".trimIndent(),
33+
),
34+
).associateBy { it.name }
35+
36+
fun getDocumentation(directiveName: String): ParameterDoc? {
37+
return directives[directiveName]
38+
}
39+
}
Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,49 @@
11
package com.github.xepozz.php_opcodes_language.language.documentation
22

3+
import com.github.xepozz.php_opcodes_language.language.psi.PHPOpParameter
34
import com.intellij.lang.documentation.AbstractDocumentationProvider
45
import com.intellij.markdown.utils.lang.CodeBlockHtmlSyntaxHighlighter
56
import com.intellij.psi.PsiElement
67

78
class PHPOpDocumentationProvider : AbstractDocumentationProvider() {
89
override fun getQuickNavigateInfo(element: PsiElement?, originalElement: PsiElement?): String? {
9-
return null
10+
if (element !is PHPOpParameter) return null
11+
12+
print("element doc $element, ${element.text}")
13+
val directiveName = element.text!!
14+
val doc = OpcodesDictionary.getDocumentation(directiveName) ?: return null
15+
16+
return doc.description
1017
}
1118

1219
override fun generateDoc(element: PsiElement?, originalElement: PsiElement?): String? {
13-
return null
20+
if (element !is PHPOpParameter) return null
21+
22+
val directiveName = element.text!!
23+
val doc = OpcodesDictionary.getDocumentation(directiveName) ?: return null
24+
val highlighter = CodeBlockHtmlSyntaxHighlighter(element.project)
25+
26+
return buildString {
27+
append("<div class='definition'><pre>")
28+
append(doc.name)
29+
append("</pre></div>")
30+
31+
append("<div class='content'>")
32+
append("<p>${doc.description}}</p>")
33+
34+
if (doc.example_php != null) {
35+
append("<h3>Example PHP</h3>")
36+
append("<pre>${highlighter.color("InjectablePHP", doc.example_php)}</pre>")
37+
}
38+
39+
if (doc.example_opcode != null) {
40+
append("<h3>Example Opcodes</h3>")
41+
append("<pre>")
42+
append("<pre>${highlighter.color("PHP Opcodes", doc.example_opcode)}</pre>")
43+
append("</pre>")
44+
}
45+
46+
append("</div>")
47+
}
1448
}
1549
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package com.github.xepozz.php_opcodes_language.language.documentation
22

3-
data class PHPOpcodeDoc(
3+
data class ParameterDoc(
44
val name: String,
5+
val number: Int,
56
val description: String,
6-
val syntax: String? = null,
7-
val examples: String? = null
7+
val example_php: String? = null,
8+
val example_opcode: String? = null
89
)

src/main/kotlin/com/github/xepozz/php_opcodes_language/language/parser/PHPOp.bnf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ statements ::= (statement | COMMENT | EOL)+
3939
statement ::= NUMBER (assignment_instruction | instruction) | live_range
4040

4141
assignment_instruction ::= parameter EQUALS_SIGN instruction
42-
instruction ::= instruction_name argument*
43-
instruction_name ::= IDENTIFIER
42+
instruction ::= parameter argument*
4443

4544
argument ::= expr | paren_expr
4645
private expr ::= var_name | string_literal | NUMBER | paren_parameter | parameter | EQUALS_SIGN
@@ -55,6 +54,7 @@ parameter ::= IDENTIFIER
5554
{
5655
implements=["com.intellij.psi.NavigatablePsiElement" "com.intellij.psi.PsiNamedElement" "com.intellij.psi.PsiPolyVariantReference"]
5756
extends="com.github.xepozz.php_opcodes_language.language.psi.impl.PHPOpParameterBaseImpl"
57+
methods=[isVariable]
5858
}
5959

6060
string_literal ::= TEXT

src/main/kotlin/com/github/xepozz/php_opcodes_language/language/psi/impl/PHPOpParameterBaseImpl.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ abstract class PHPOpParameterBaseImpl : PHPOpParameter, PHPOpElementImpl {
4242
throw UnsupportedOperationException("Method bindToElement is not yet implemented in " + this.javaClass.getName())
4343
}
4444

45-
override fun isReferenceTo(psiElement: PsiElement): Boolean {
46-
return when (psiElement) {
47-
is PHPOpParameter -> this.text == psiElement.text
48-
else -> false
45+
override fun isReferenceTo(psiElement: PsiElement) = when (psiElement) {
46+
!is PHPOpParameter -> false
47+
else -> when (true) {
48+
!psiElement.isVariable -> false
49+
else -> this.text == psiElement.text
4950
}
5051
}
5152

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.github.xepozz.php_opcodes_language.language.psi.impl
2+
3+
import com.github.xepozz.php_opcodes_language.language.psi.PHPOpParameter
4+
5+
class PHPOpPsiImplUtil {
6+
companion object {
7+
@JvmStatic
8+
fun isVariable(element: PHPOpParameter): Boolean = element.text.startsWith("$")
9+
}
10+
}

0 commit comments

Comments
 (0)