Skip to content

Commit 98b5f99

Browse files
authored
Merge pull request #335 from Haehnchen/feature/upgrade-build
Upgrade Gradle and plugins, update configurations
2 parents 6121733 + f21635b commit 98b5f99

29 files changed

Lines changed: 456 additions & 184 deletions

CLAUDE.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is an IntelliJ IDEA/PhpStorm plugin that provides PHP annotation and PHP 8 Attribute support. The plugin extends the IDE to recognize annotation classes marked with `@Annotation`, provides code completion, navigation, inspections, and integrates with Doctrine ORM and Symfony frameworks.
8+
9+
**Plugin ID**: `de.espend.idea.php.annotation`
10+
11+
## Build Commands
12+
13+
### Build the plugin
14+
```bash
15+
./gradlew buildPlugin
16+
```
17+
The plugin ZIP will be in `build/distributions/`.
18+
19+
### Run tests
20+
```bash
21+
./gradlew test
22+
```
23+
24+
### Run a single test class
25+
```bash
26+
./gradlew test --tests "de.espend.idea.php.annotation.tests.AnnotationStubIndexTest"
27+
```
28+
29+
### Run a single test method
30+
```bash
31+
./gradlew test --tests "de.espend.idea.php.annotation.tests.AnnotationStubIndexTest.testThatAnnotationClassIsInIndex"
32+
```
33+
34+
### Run the plugin in a test IDE instance
35+
```bash
36+
./gradlew runIde
37+
```
38+
39+
### Verify plugin compatibility
40+
```bash
41+
./gradlew verifyPlugin
42+
```
43+
44+
### Clean build
45+
```bash
46+
./gradlew clean buildPlugin
47+
```
48+
49+
## Architecture
50+
51+
### Extension Point System
52+
53+
The plugin's core architecture is based on extension points that allow both internal components and external plugins (like Symfony Support or PHP Toolbox) to extend functionality.
54+
55+
**Key extension point interfaces** (in `src/main/java/de/espend/idea/php/annotation/extension/`):
56+
57+
- **PhpAnnotationCompletionProvider**: Provides code completion for annotation property values
58+
- **PhpAnnotationReferenceProvider**: Provides references and navigation for annotation elements
59+
- **PhpAnnotationDocTagGotoHandler**: Handles "Go to Declaration" for annotation tags
60+
- **PhpAnnotationDocTagAnnotator**: Provides custom highlighting/error annotations for doc tags
61+
- **PhpAnnotationGlobalNamespacesLoader**: Loads global annotation namespace mappings
62+
- **PhpAnnotationVirtualProperties**: Provides virtual properties for annotation classes
63+
- **PhpAnnotationUseAlias**: Maps custom class aliases (e.g., "ORM" => "Doctrine\\ORM\\Mapping")
64+
65+
Extension points are registered in `src/main/resources/META-INF/plugin.xml` and can be used by other plugins.
66+
67+
### Indexing System
68+
69+
The plugin uses two main file-based indices for fast lookup:
70+
71+
- **AnnotationStubIndex**: Indexes all PHP classes marked with `@Annotation` in their doc block
72+
- **AnnotationUsageIndex**: Indexes where annotations are used in the codebase
73+
74+
These indices power the navigation features (find usages, line markers) and are updated automatically when files change.
75+
76+
### Module Organization
77+
78+
- **annotator/**: Provides inline error highlighting and warnings
79+
- **completion/**: Code completion contributors and providers
80+
- **dict/**: Data transfer objects and dictionary classes
81+
- **doctrine/**: Doctrine ORM-specific features (property generators, repository class handling, column type support)
82+
- **extension/**: Extension point interfaces and parameters
83+
- **inspection/**: Code inspections (missing imports, deprecated usage, etc.)
84+
- **navigation/**: Navigation handlers and line marker providers
85+
- **pattern/**: PSI pattern matching for identifying annotation contexts
86+
- **reference/**: Reference contributors for navigation and "Find Usages"
87+
- **symfony/**: Symfony-specific annotation support
88+
- **toolbox/**: PHP Toolbox integration
89+
- **ui/**: Settings forms and configuration UI
90+
- **util/**: Utility classes, particularly `AnnotationUtil` which contains core logic for annotation detection and processing
91+
92+
### Dual Support: DocBlock Annotations and PHP 8 Attributes
93+
94+
The plugin supports both:
95+
- **DocBlock annotations**: `/** @Route("/path") */`
96+
- **PHP 8 Attributes**: `#[Route('/path')]`
97+
98+
Extension points work transparently with both formats, allowing feature implementations to support both simultaneously.
99+
100+
## Key Concepts
101+
102+
### Annotation Detection
103+
104+
Classes are recognized as annotation classes if they have `@Annotation` in their doc block:
105+
```php
106+
/**
107+
* @Annotation
108+
* @Target("METHOD", "CLASS")
109+
*/
110+
class Route {
111+
public $path;
112+
}
113+
```
114+
115+
### Target Filtering
116+
117+
The `@Target` annotation restricts where annotations can be used (METHOD, CLASS, PROPERTY, ALL). The plugin uses this for completion filtering.
118+
119+
### Property Type Detection
120+
121+
Annotation properties support type hints via doc comments:
122+
- Simple types: `@var string`, `@var bool`
123+
- Arrays: `@var array<string>`
124+
- Enums: `@Enum({"GET", "POST", "PUT"})`
125+
- Mixed: `@var mixed|string|bool`
126+
127+
### Use Alias System
128+
129+
The plugin supports configurable namespace aliases (Settings > PHP > Annotations / Attributes > Use Alias):
130+
- Maps short names to FQCNs: `ORM` => `Doctrine\ORM\Mapping`
131+
- Auto-import suggestions use these mappings
132+
- External plugins can provide their own mappings via `PhpAnnotationUseAlias` extension point
133+
134+
## Test Structure
135+
136+
Tests extend `AnnotationLightCodeInsightFixtureTestCase` which provides a test fixture framework.
137+
138+
Test data files are in `src/test/java/de/espend/idea/php/annotation/tests/fixtures/`.
139+
140+
Tests use the `myFixture` field to:
141+
- Copy test PHP files: `myFixture.copyFileToProject("classes.php")`
142+
- Check completion: `myFixture.completeBasic()`
143+
- Navigate: `myFixture.getReferenceAtCaretPosition()`
144+
- Assert index contents: `assertIndexContains(AnnotationStubIndex.KEY, "My\\Class")`
145+
146+
## Configuration
147+
148+
Build configuration is in `gradle.properties`:
149+
- `platformVersion`: Target IntelliJ/PhpStorm version (currently 2025.2.5)
150+
- `pluginSinceBuild` / `pluginUntilBuild`: Supported IDE version range
151+
- `javaVersion`: Java language level (21)
152+
153+
The plugin requires these IntelliJ plugins as dependencies:
154+
- `com.jetbrains.php` (PhpStorm PHP support)
155+
- `com.jetbrains.twig` (Twig template support)
156+
- `com.intellij.modules.json` (JSON support)
157+
158+
Optional integration:
159+
- `de.espend.idea.php.toolbox` (PHP Toolbox)
160+
161+
## Publishing
162+
163+
See `MAINTENANCE.md` for the full release process. Key steps:
164+
1. Update `CHANGELOG.md`
165+
2. Commit changes
166+
3. Tag release: `git tag X.Y.Z`
167+
4. Build: `./gradlew clean buildPlugin`
168+
5. Publish: `IJ_TOKEN=yourtoken ./gradlew publishPlugin`

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
IntelliJ IDEA - PhpStorm PHP Annotations / Attributes
22
==========================
33
[![Build Status](https://github.com/Haehnchen/idea-php-annotation-plugin/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/Haehnchen/idea-php-annotation-plugin/actions/workflows/gradle.yml)
4+
[![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/Haehnchen/idea-php-annotation-plugin)
45
[![Version](http://phpstorm.espend.de/badge/7320/version)](https://plugins.jetbrains.com/plugin/7320)
56
[![Downloads](http://phpstorm.espend.de/badge/7320/downloads)](https://plugins.jetbrains.com/plugin/7320)
67
[![Downloads last month](http://phpstorm.espend.de/badge/7320/last-month)](https://plugins.jetbrains.com/plugin/7320)

build.gradle.kts

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ fun properties(key: String) = project.findProperty(key).toString()
55

66
plugins {
77
id("java")
8-
id("org.jetbrains.kotlin.jvm") version "2.0.0"
9-
id("org.jetbrains.intellij.platform") version "2.4.0"
8+
id("org.jetbrains.kotlin.jvm") version "2.2.21"
9+
id("org.jetbrains.intellij.platform") version "2.10.4"
1010
id("org.jetbrains.changelog") version "1.3.1"
1111
id("org.jetbrains.qodana") version "0.1.13"
1212
}
@@ -27,27 +27,46 @@ dependencies {
2727
intellijPlatform {
2828
val version = providers.gradleProperty("platformVersion")
2929
val type = providers.gradleProperty("platformType")
30-
create(type, version, useInstaller = false)
30+
create(type, version) {
31+
useInstaller = false
32+
useCache = true
33+
}
3134

32-
bundledPlugins(properties("platformBundledPlugins").split(',').map(String::trim).filter(String::isNotEmpty))
33-
plugins(properties("platformPlugins").split(',').map(String::trim).filter(String::isNotEmpty))
35+
bundledPlugins("com.intellij.java", "com.jetbrains.plugins.webDeployment")
3436

37+
compatiblePlugins(
38+
"com.jetbrains.php",
39+
"com.jetbrains.twig",
40+
"com.intellij.modules.json",
41+
"de.espend.idea.php.toolbox"
42+
)
3543
testFramework(TestFrameworkType.Platform)
3644
testFramework(TestFrameworkType.Plugin.Java)
3745
}
3846

3947
testImplementation("junit:junit:4.13.2")
40-
testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")
41-
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2")
48+
testImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
49+
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.11.4")
50+
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.11.4")
4251
}
4352

4453
// Configure Gradle IntelliJ Plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
4554
intellijPlatform {
55+
val version = providers.gradleProperty("platformVersion")
56+
val type = providers.gradleProperty("platformType")
57+
4658
pluginConfiguration {
4759
name = properties("pluginName")
4860
}
49-
instrumentCode = false
50-
buildSearchableOptions = false
61+
62+
pluginVerification {
63+
ides {
64+
create(type, version) {
65+
useInstaller = false
66+
useCache = true
67+
}
68+
}
69+
}
5170
}
5271

5372
// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
@@ -72,7 +91,9 @@ tasks {
7291
targetCompatibility = it
7392
}
7493
withType<KotlinCompile> {
75-
kotlinOptions.jvmTarget = it
94+
compilerOptions {
95+
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(it))
96+
}
7697
}
7798
}
7899

@@ -85,31 +106,6 @@ tasks {
85106
sinceBuild.set(properties("pluginSinceBuild"))
86107
untilBuild.set(properties("pluginUntilBuild"))
87108
changeNotes.set(file("src/main/resources/META-INF/change-notes.html").readText().replace("<html>", "").replace("</html>", ""))
88-
89-
// Get the latest available change notes from the changelog file
90-
// changeNotes.set(provider {
91-
// changelog.run {
92-
// getOrNull(properties("pluginVersion")) ?: getLatest()
93-
// }.toHTML()
94-
// })
95-
}
96-
97-
// Configure UI tests plugin
98-
// Read more: https://github.com/JetBrains/intellij-ui-test-robot
99-
intellijPlatformTesting.runIde.registering {
100-
task {
101-
jvmArgumentProviders += CommandLineArgumentProvider {
102-
listOf(
103-
"-Drobot-server.port=8082",
104-
"-Dide.mac.message.dialogs.as.sheets=false",
105-
"-Djb.privacy.policy.text=<!--999.999-->",
106-
"-Djb.consents.confirmation.enabled=false",
107-
)
108-
}
109-
}
110-
plugins {
111-
robotServerPlugin()
112-
}
113109
}
114110

115111
signPlugin {
@@ -119,18 +115,13 @@ tasks {
119115
}
120116

121117
publishPlugin {
122-
// dependsOn("patchChangelog")
123-
token.set(System.getenv("PUBLISH_TOKEN"))
124-
// pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
125-
// Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more:
126-
// https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel
127-
// channels.set(listOf(properties("pluginVersion").split('-').getOrElse(1) { "default" }.split('.').listIterator()))
118+
token.set(System.getenv("PUBLISH_TOKEN"))
128119
}
129120

130121
test {
131122
// Support "setUp" like "BasePlatformTestCase::setUp" as valid test structure
132123
useJUnitPlatform {
133-
includeEngines("junit-vintage")
124+
includeEngines("junit-vintage", "junit-jupiter")
134125
}
135126
}
136127
}

gradle.properties

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,22 @@ pluginVersion = 12.0.1
99

1010
# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1111
# for insight into build numbers and IntelliJ Platform versions.
12-
pluginSinceBuild = 251
12+
pluginSinceBuild = 252
1313
pluginUntilBuild = 299.*
1414

1515
# IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties
1616
platformType = IU
17-
platformVersion = 2025.1
17+
platformVersion = 2025.2.5
1818

19-
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
20-
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
21-
platformBundledPlugins = com.intellij.java,com.jetbrains.plugins.webDeployment
22-
platformPlugins = com.jetbrains.php:251.23774.318,com.jetbrains.twig:251.23774.318,de.espend.idea.php.toolbox:6.2.0,com.intellij.modules.json:251.23774.318
23-
24-
# Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3
19+
# Java language level used to compile sources and to generate the files for
2520
javaVersion = 21
2621

2722
# Gradle Releases -> https://github.com/gradle/gradle/releases
28-
gradleVersion = 8.13
23+
gradleVersion = 9.2.1
2924

3025
# Opt-out flag for bundling Kotlin standard library.
3126
# See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details.
3227
# suppress inspection "UnusedProperty"
3328
kotlin.stdlib.default.dependency = false
29+
30+
org.gradle.configuration-cache=true

gradle/wrapper/gradle-wrapper.jar

243 Bytes
Binary file not shown.

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

gradlew

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)