Skip to content

Commit ae69ecd

Browse files
authored
Merge pull request #7 from tommykw/feature/phpstorm-target
feat: target PhpStorm for trait viewer plugin
2 parents 8e3cecc + fe0e829 commit ae69ecd

File tree

11 files changed

+157
-141
lines changed

11 files changed

+157
-141
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ platformVersion = 2025.2.5
1414

1515
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1616
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
17-
platformPlugins =
17+
platformPlugins = com.jetbrains.php:252.28238.7
1818
# Example: platformBundledPlugins = com.intellij.java
1919
platformBundledPlugins =
2020
# Example: platformBundledModules = intellij.spellchecker

src/main/kotlin/com/github/tommykw/phptraitinlineviewer/MyBundle.kt

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.github.tommykw.phptraitinlineviewer
2+
3+
import com.intellij.notification.NotificationGroupManager
4+
import com.intellij.notification.NotificationType
5+
import com.intellij.openapi.project.Project
6+
7+
object TraitInlineNotifier {
8+
private const val GROUP_ID = "Trait Inline Viewer"
9+
10+
fun warn(project: Project, message: String) {
11+
NotificationGroupManager.getInstance()
12+
.getNotificationGroup(GROUP_ID)
13+
.createNotification(message, NotificationType.WARNING)
14+
.notify(project)
15+
}
16+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.github.tommykw.phptraitinlineviewer
2+
3+
import com.intellij.openapi.actionSystem.AnAction
4+
import com.intellij.openapi.actionSystem.AnActionEvent
5+
import com.intellij.openapi.actionSystem.CommonDataKeys
6+
import com.intellij.psi.util.PsiTreeUtil
7+
import com.jetbrains.php.lang.psi.PhpFile
8+
import com.jetbrains.php.lang.psi.elements.PhpClass
9+
import com.jetbrains.php.lang.psi.elements.PhpTraitUseRule
10+
11+
class TraitInlineViewerAction : AnAction() {
12+
override fun update(event: AnActionEvent) {
13+
event.presentation.text = "View PHP Trait Inline"
14+
15+
val psiFile = event.getData(CommonDataKeys.PSI_FILE)
16+
val editor = event.getData(CommonDataKeys.EDITOR)
17+
val isPhpFile = psiFile is PhpFile
18+
19+
event.presentation.isVisible = isPhpFile
20+
21+
if (!isPhpFile || editor == null) {
22+
event.presentation.isEnabled = false
23+
event.presentation.description = "Available only inside PHP editors."
24+
return
25+
}
26+
27+
// Check if cursor is in or near a PHP trait use
28+
val element = psiFile.findElementAt(editor.caretModel.offset)
29+
val traitUseRule = element?.let { PsiTreeUtil.getParentOfType(it, PhpTraitUseRule::class.java) }
30+
val phpClass = traitUseRule?.let { PsiTreeUtil.getParentOfType(it, PhpClass::class.java) }
31+
?: element?.let { PsiTreeUtil.getParentOfType(it, PhpClass::class.java) }
32+
33+
if (phpClass == null) {
34+
event.presentation.isEnabled = false
35+
event.presentation.description = "Place the caret inside a PHP class."
36+
return
37+
}
38+
39+
val hasTraitUses = phpClass.traitUseRules()?.isEmpty == false
40+
event.presentation.isEnabled = hasTraitUses
41+
event.presentation.description = if (hasTraitUses) {
42+
"Open an inline view of ${phpClass.name ?: "this class"} with merged traits."
43+
} else {
44+
"No trait use statements found in ${phpClass.name ?: "this class"}."
45+
}
46+
}
47+
48+
override fun actionPerformed(event: AnActionEvent) {
49+
val project = event.project ?: return
50+
val editor = event.getData(CommonDataKeys.EDITOR)
51+
val psiFile = event.getData(CommonDataKeys.PSI_FILE)
52+
53+
if (psiFile !is PhpFile || editor == null) {
54+
TraitInlineNotifier.warn(project, "Place the caret inside a PHP editor before running this action.")
55+
return
56+
}
57+
58+
val element = psiFile.findElementAt(editor.caretModel.offset)
59+
60+
if (element == null) {
61+
TraitInlineNotifier.warn(project, "Could not locate PSI element at the caret position.")
62+
return
63+
}
64+
65+
val phpClass = PsiTreeUtil.getParentOfType(element, PhpClass::class.java)
66+
if (phpClass == null) {
67+
TraitInlineNotifier.warn(project, "This action must be triggered from inside a PHP class.")
68+
return
69+
}
70+
71+
if (phpClass.traitUseRules()?.isEmpty != false) {
72+
TraitInlineNotifier.warn(project, "${phpClass.name ?: "This class"} does not use any traits.")
73+
return
74+
}
75+
76+
val merged = TraitMerger.mergeClassWithTraits(phpClass)
77+
TraitInlineFileOpener.open(project, merged, phpClass.name ?: "Unknown")
78+
}
79+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.github.tommykw.phptraitinlineviewer
2+
3+
import com.intellij.openapi.fileEditor.FileEditorManager
4+
import com.intellij.openapi.project.Project
5+
import com.intellij.testFramework.LightVirtualFile
6+
import com.jetbrains.php.lang.PhpFileType
7+
import com.jetbrains.php.lang.psi.elements.PhpClass
8+
9+
object TraitMerger {
10+
fun mergeClassWithTraits(phpClass: PhpClass): String {
11+
return buildString {
12+
append("<?php\n\n")
13+
append("class ${phpClass.name}Merged {\n")
14+
15+
val traits = phpClass.traits
16+
17+
for (trait in traits) {
18+
append(" // ===== Trait: ${trait.name} =====\n\n")
19+
20+
for (method in trait.methods) {
21+
append(" ")
22+
append(method.text.replace("\n", "\n "))
23+
append("\n\n")
24+
}
25+
26+
for (field in trait.fields) {
27+
append(" ")
28+
append(field.text.replace("\n", "\n "))
29+
append("\n\n")
30+
}
31+
}
32+
33+
append("}\n")
34+
}
35+
}
36+
}
37+
38+
object TraitInlineFileOpener {
39+
fun open(project: Project, content: String, originalClassName: String) {
40+
val file = LightVirtualFile(
41+
"${originalClassName}_InlineTraits.php",
42+
PhpFileType.INSTANCE,
43+
content
44+
)
45+
file.isWritable = false
46+
47+
FileEditorManager.getInstance(project).openFile(file, true)
48+
}
49+
}

src/main/kotlin/com/github/tommykw/phptraitinlineviewer/services/MyProjectService.kt

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/main/kotlin/com/github/tommykw/phptraitinlineviewer/startup/MyProjectActivity.kt

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/main/kotlin/com/github/tommykw/phptraitinlineviewer/toolWindow/MyToolWindowFactory.kt

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/main/resources/META-INF/plugin.xml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@
55
<vendor>tommykw</vendor>
66

77
<depends>com.intellij.modules.platform</depends>
8-
9-
<resource-bundle>messages.MyBundle</resource-bundle>
8+
<depends>com.jetbrains.php</depends>
109

1110
<extensions defaultExtensionNs="com.intellij">
12-
<toolWindow factoryClass="com.github.tommykw.phptraitinlineviewer.toolWindow.MyToolWindowFactory" id="MyToolWindow"/>
13-
<postStartupActivity implementation="com.github.tommykw.phptraitinlineviewer.startup.MyProjectActivity" />
11+
<notificationGroup id="Trait Inline Viewer" displayType="BALLOON" isLogByDefault="false"/>
1412
</extensions>
13+
14+
<actions>
15+
<action id="com.github.tommykw.phptraitinlineviewer.TraitInlineViewerAction"
16+
class="com.github.tommykw.phptraitinlineviewer.TraitInlineViewerAction"
17+
text="View PHP Trait Inline"
18+
19+
description="View PHP class with traits merged inline">
20+
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
21+
</action>
22+
</actions>
1523
</idea-plugin>

src/main/resources/messages/MyBundle.properties

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)