Skip to content

Commit 6e54137

Browse files
committed
Add guidelines and tests for implementing PHP interfaces
Introduce `guidelines.md` for development standards and project setup. Add tests for `MoodlePHPNewClassAction` to validate PHP interface implementation. Update implementation logic to handle `implements` clause modifications.
1 parent 0325f12 commit 6e54137

3 files changed

Lines changed: 131 additions & 3 deletions

File tree

.junie/guidelines.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Moodle Plugin Development Guidelines
2+
3+
## Project Overview
4+
This is an IntelliJ Platform plugin project for Moodle development support.
5+
6+
## Tech Stack
7+
- Kotlin
8+
- Gradle (with Kotlin DSL)
9+
- IntelliJ Platform SDK
10+
- JUnit for testing
11+
- Kover for code coverage
12+
- Qodana for code quality
13+
14+
## Project Structure
15+
```
16+
.
17+
├── src/
18+
│ ├── main/kotlin/ # Source code
19+
│ ├── main/resources/ # Resources (icons, templates)
20+
│ │ └── META-INF/ # Plugin configuration
21+
│ └── test/ # Test files
22+
├── .run/ # Run configurations
23+
├── build.gradle.kts # Gradle build configuration
24+
├── gradle.properties # Gradle properties
25+
├── qodana.yml # Code quality settings
26+
└── README.md # Project documentation
27+
```
28+
29+
## Configuration Files
30+
- `src/main/resources/META-INF/plugin.xml`: Core plugin configuration
31+
- `qodana.yml`: Code quality analysis settings
32+
- `gradle.properties`: Gradle and plugin properties
33+
- `.run/`: IDE run configurations
34+
35+
## Build & Run
36+
1. Setup:
37+
```bash
38+
./gradlew clean
39+
```
40+
2. Build:
41+
```bash
42+
./gradlew build
43+
```
44+
3. Run IDE with plugin:
45+
```bash
46+
./gradlew runIde
47+
```
48+
49+
## Testing
50+
- Run tests:
51+
```bash
52+
./gradlew test
53+
```
54+
- Run with coverage:
55+
```bash
56+
./gradlew koverReport
57+
```
58+
- UI Tests:
59+
```bash
60+
./gradlew runIdeForUiTests
61+
```
62+
63+
## Development Guidelines
64+
1. Use Kotlin coding conventions
65+
2. Add tests for new features
66+
3. Update CHANGELOG.md for changes
67+
4. Follow semantic versioning
68+
5. Keep plugin.xml up to date
69+
70+
## Useful Commands
71+
- Clean and build: `./gradlew clean build`
72+
- Run plugin verifier: `./gradlew runPluginVerifier`
73+
- Generate coverage report: `./gradlew koverReport`
74+
- Publish plugin: `./gradlew publishPlugin`

src/main/kotlin/il/co/sysbind/intellij/moodledev/actions/generation/MoodlePHPNewClassAction.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ import com.jetbrains.php.lang.PhpLangUtil
2020
import com.jetbrains.php.lang.inspections.classes.PhpAddMethodStubsQuickFix
2121
import com.jetbrains.php.lang.intentions.PhpImportClassIntention
2222
import com.jetbrains.php.lang.psi.PhpGroupUseElement.PhpUseKeyword
23+
import com.jetbrains.php.lang.psi.PhpPsiElementFactory
2324
import com.jetbrains.php.lang.psi.elements.Method
2425
import com.jetbrains.php.lang.psi.elements.PhpClass
2526
import com.jetbrains.php.lang.psi.elements.PhpPsiElement
26-
import com.jetbrains.php.refactoring.extract.extractInterface.PhpExtractInterfaceProcessor
2727
import com.jetbrains.php.templates.PhpCreateFileFromTemplateDataProvider
2828
import com.jetbrains.php.templates.PhpTemplatesSettings
2929
import il.co.sysbind.intellij.moodledev.project.MoodleProjectSettings
@@ -178,7 +178,12 @@ class MoodlePHPNewClassAction : PhpNewBaseAction(CAPTION, "", PhpFileType.INSTAN
178178
if (!StringUtil.isEmpty(interfaceToImplement) && implementedInterfaces.add(interfaceFqn)) {
179179
val interfaceQualifiedName =
180180
if (scope != null) PhpCodeInsightUtil.createQualifiedName(scope, interfaceFqn) else interfaceFqn
181-
PhpExtractInterfaceProcessor.addImplementClause(project, phpClass, interfaceQualifiedName)
181+
val implementsClause = PhpPsiElementFactory.createImplementsList(project, interfaceQualifiedName)
182+
if (phpClass.implementsList != null) {
183+
phpClass.implementsList!!.add(implementsClause)
184+
} else {
185+
phpClass.add(implementsClause)
186+
}
182187
if (PhpReferenceInsertHandler.shouldInsertImport(phpClass, phpClass, interfaceFqn)) {
183188
PhpImportClassIntention.apply(
184189
project,
@@ -206,4 +211,4 @@ class MoodlePHPNewClassAction : PhpNewBaseAction(CAPTION, "", PhpFileType.INSTAN
206211
phpClass.methods
207212
) { method: Method -> method.isAbstract && method.containingClass !== phpClass }
208213
}
209-
}
214+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package il.co.sysbind.intellij.moodledev.actions.generation
2+
3+
import com.intellij.openapi.command.WriteCommandAction
4+
import com.intellij.psi.PsiFile
5+
import com.intellij.psi.util.PsiTreeUtil
6+
import com.intellij.testFramework.fixtures.BasePlatformTestCase
7+
import com.jetbrains.php.lang.psi.elements.PhpClass
8+
import com.jetbrains.php.lang.psi.elements.PhpPsiElement
9+
10+
class MoodlePHPNewClassActionTest : BasePlatformTestCase() {
11+
fun testImplementInterfaces() {
12+
// Create a PHP file with a class
13+
val phpFile = myFixture.configureByText(
14+
"test.php",
15+
"""<?php
16+
class TestClass {
17+
}
18+
"""
19+
)
20+
21+
// Get the class from the file
22+
val phpClass = PsiTreeUtil.findChildOfType(phpFile, PhpClass::class.java)
23+
assertNotNull("PHP class should be created", phpClass)
24+
25+
// Create an instance of MoodlePHPNewClassAction
26+
val action = MoodlePHPNewClassAction()
27+
28+
// Call implementInterfaces through reflection since it's private
29+
val method = MoodlePHPNewClassAction::class.java.getDeclaredMethod(
30+
"implementInterfaces",
31+
PhpClass::class.java,
32+
PhpPsiElement::class.java,
33+
Collection::class.java
34+
)
35+
method.isAccessible = true
36+
37+
// Test implementing an interface
38+
WriteCommandAction.runWriteCommandAction(project) {
39+
method.invoke(action, phpClass, phpClass, listOf("\\TestInterface"))
40+
}
41+
42+
// Verify the interface was added
43+
assertEquals(
44+
"Interface should be implemented",
45+
"\\TestInterface",
46+
phpClass?.implementsList?.referenceElements?.firstOrNull()?.fqn
47+
)
48+
}
49+
}

0 commit comments

Comments
 (0)